How to add common functionalities to structs by way of inheritance without having to explicitly initialize the base struct?

huangapple go评论61阅读模式
英文:

How to add common functionalities to structs by way of inheritance without having to explicitly initialize the base struct?

问题

我有一些结构体,它们都具有一些共同的功能,我已经将它们放在了一个模板基类中(这里是 Foo<int>

template<int I>
struct Foo
{
    void foo() { std::cout << "foo: " << I << '\n'; }
};

struct Bar : Foo<1>
{
    int i;
    int j;
};

现在,当我初始化它们中的任何一个时,我必须这样做:

Bar b{{}, 1, 2};

我想能够这样做:

Bar b{1, 2};

而且不需要编写构造函数的样板代码。是否有解决这个问题的方法?

类似的问题已经在这里提出过,但那是7年前的事情了,所以我想知道是否有新的进展。

此外,那个问题被标记为一个问题的重复这里,但这个问题稍微不同,因为基本结构体不是空的。

另外,我不是真的在尝试实现其他任何目标,只是想以更声明性的方式为一些结构体添加功能,而不是在每个结构体中重复所有共同方法的定义。因此,任何实现这一目标的解决方案(最好是不使用继承,除非使用宏 ;D)也可以接受。

英文:

I have some structs that all have some common functionalities that I've put in an templated base class (here Foo&lt;int&gt;)

template&lt;int I&gt;
struct Foo
{
    void foo() { std::cout &lt;&lt; &quot;foo: &quot; &lt;&lt; I &lt;&lt; &#39;\n&#39;; }
};

struct Bar : Foo&lt;1&gt;
{
    int i;
    int j;
};

Now when I initialize any of them I have to do it like so:

Bar b{{}, 1, 2};

And I would like to be able to do it like so:

Bar b{1, 2};

And also without the boilerplate of having to write a constructor.
Is there some solution to this problem?

A similar question was asked here, however, this was over 7 years ago, so I was wondering if there were any developments since then.
Also, that question is marked duplicate of a question here, however this one is slightly different, as the base struct is not empty.
In addition, I'm not really trying to accomplish anything other than adding functionality to some structures, in a more declarative way, rather than repeating the definitions of all the common methods in each of them. So any solution that achieves that, by circumventing inheritance (apart from macros ideally ;D) would work as well.

答案1

得分: 5

你可以在这里使用指定的初始化程序:

Bar b{.i = 1, .j = 2};

你还可以将聚合结构struct { int i; int j; }作为首个继承的元素。以下是两种实现方式:

template<int I>
struct Foo
{
    void foo() { std::cout << "foo: " << I << '\n'; }
};

struct BarBase {
    int i;
    int j;
};

struct Bar : BarBase, Foo<1> {};

Bar x{{.i = 1, .j = 2}};
Bar y{1, 2};
// 这种方式还允许您访问基类。
// 这是一种用于混合的常见模式,这就是Foo的作用
template<typename Base, int I>
struct Foo : Base
{
    void foo() { std::cout << "foo: " << I << '\n'; }
};

struct BarBase {
    int i;
    int j;
};

using Bar = Foo<BarBase, 1>;

Bar x{{.i = 1, .j = 2}};
Bar y{1, 2};
英文:

You can use designated initializers here:

Bar b{.i = 1, .j = 2};

You can also make the aggregate struct { int i; int j; } the first thing inherited from. Here are two ways you can make that happen:

template&lt;int I&gt;
struct Foo
{
    void foo() { std::cout &lt;&lt; &quot;foo: &quot; &lt;&lt; I &lt;&lt; &#39;\n&#39;; }
};

struct BarBase {
    int i;
    int j;
};

struct Bar : BarBase, Foo&lt;1&gt; {};

Bar x{{.i = 1, .j = 2}};
Bar y{1, 2};
// This way also allows you to access the base.
// A common pattern for mixins, which is what Foo is
template&lt;typename Base, int I&gt;
struct Foo : Base
{
    void foo() { std::cout &lt;&lt; &quot;foo: &quot; &lt;&lt; I &lt;&lt; &#39;\n&#39;; }
};

struct BarBase {
    int i;
    int j;
};

using Bar = Foo&lt;BarBase, 1&gt;;

Bar x{{.i = 1, .j = 2}};
Bar y{1, 2};

huangapple
  • 本文由 发表于 2023年5月22日 20:08:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76306038.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定