使用空基类的聚合初始化时如何避免
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<int, 2> 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 中。以上是关于使用空基类的聚合初始化时如何避免的主要内容,如果未能解决你的问题,请参考以下文章