使用空基类的聚合初始化时如何避免

Posted

技术标签:

【中文标题】使用空基类的聚合初始化时如何避免【英文标题】:How to avoid when using aggregate initialization with empty base class 【发布时间】:2019-08-30 17:27:26 【问题描述】:

C++17 对基类的聚合初始化很棒,但是当基类只是提供一些功能(所以没有数据成员)时,它就很冗长了。

这是最小的例子:

#include <cstddef>
struct base_pod

    // functions like friend compare operator
;
template<typename T, std::size_t N>
struct der_pod : public base_pod

    T k[N];
;

int main()

    der_pod<int, 2> dp , 3, 3 ;

如上例所示,我必须提供空的,否则会出现编译错误。 live demo。如果我省略它:

prog.cc:15:28: error: initializer for aggregate with no elements requires explicit braces
        der_pod<int, 2> dp3, 3;
                           ^
prog.cc:15:31: warning: suggest braces around initialization of subobject [-Wmissing-braces]
        der_pod<int, 2> dp3, 3;
                              ^
                              
1 warning and 1 error generated.

任何解决方法或 C++17 之前的方法?

【问题讨论】:

我会注意到在您的示例中与基类没有任何关系,您可以删除它并查看错误仍然存​​在godbolt.org/z/0FpuQ5 @DmitryGordon 我需要这个基类。我提供的案例只是一个小例子 Pre C++17 你不能有基类,所以这不是问题。您只需将类及其所有运算符放在命名空间中即可。 你到底使用基类做什么?必须在派生类中重写比较函数才能使其工作。 关于您显示的错误,与例如相同。 std::array:对象本身需要一对外部大括号,然后是聚合数据的内部对。如der_pod&lt;int, 2&gt; dp3, 3;。但这不起作用,因为继承和初始化基类的需要也是如此(导致初始为空)。 【参考方案1】:

你仍然可以提供构造函数,例如:

template <typename T, std::size_t N> using always_t = T;

struct base_pod

    // functions like friend compare operator
;
template<typename T, typename Seq> struct der_pod_impl;

template<typename T, std::size_t ... Is>
struct der_pod_impl<T, std::index_sequence<Is...>> : base_pod

    der_pod_impl(always_t<T, Is>... args) : kargs... 

    T k[sizeof...(Is)];
;

template<typename T, std::size_t N>
using der_pod = der_pod_impl<T, std::make_index_sequence<N>>;

Demo

【讨论】:

为什么要费尽心思将der_pod 拆分为别名模板和_impl 变体,对其进行专门化,然后编写自定义类型标识类型特征?难道推理指南不能在启用 CTAD 的同时完成所有这些(因此无需明确写出类型和大小)? @303: 可变参数模板构造函数可能确实是一种替代方案,但需要注意的是避免复制构造函数出现问题。 啊,好点子!但我确实认为具有显式默认复制构造函数的替代版本还不错:godbolt.org/z/o6j4sjPc6。除非您发现它本身有问题,否则我认为应该将其添加到您的答案 +1 中。

以上是关于使用空基类的聚合初始化时如何避免的主要内容,如果未能解决你的问题,请参考以下文章

如何避免在基类初始化程序中调用默认构造函数?

如何初始化作为另一个类的成员变量的基类对象?

初始化 C++ 基类而不键入整个基类类型两次

虚基类在解决二义性中的问题中的作用是啥

C++中如何在子类的构造函数中调用基类的构造函数来初始化基类成员变量

如何避免为聚合初始化重新输入类型信息?