[英]constructor of derived class cannot be constexpr if base class contains array member
我想使用构造函数定义派生类型(SBar)的constexpr值,该构造函数的唯一参数是基类(SFoo)的变量,它只是用于初始化基类。
当基类没有数组成员时,这很好用。 但是,当我添加一个数组时,派生值不能再是constexpr。 但是,基类的简单副本确实会产生constexpr结果。
为了安全起见,我明确默认了所有复制和移动构造函数。
TEST.CPP
#define USE_ARRAY
struct SFoo
{
constexpr SFoo() =default;
constexpr SFoo(SFoo const&) =default;
constexpr SFoo(SFoo &) =default;
constexpr SFoo(SFoo &&) =default;
constexpr SFoo& operator = (SFoo const&) =default;
constexpr SFoo& operator = (SFoo &) =default;
constexpr SFoo& operator = (SFoo &&) =default;
# ifdef USE_ARRAY
constexpr SFoo(int const (&array)[1]) :
M_array{array[0]}
{}
int M_array[1] = {0};
# else
constexpr SFoo(int value) :
M_value{value}
{}
int M_value = 0;
# endif
};
struct SBar : SFoo
{
constexpr SBar() =default;
constexpr SBar(SBar const&) =default;
constexpr SBar(SBar &) =default;
constexpr SBar(SBar &&) =default;
constexpr SBar& operator = (SBar const&) =default;
constexpr SBar& operator = (SBar &) =default;
constexpr SBar& operator = (SBar &&) =default;
constexpr SBar(SFoo foo) : SFoo(foo) {}
};
// Instances:
# ifdef USE_ARRAY
constexpr int arg[1] = {3};
# else
constexpr int arg = 3;
# endif
constexpr SFoo foo(arg); // base "value" constructor is constexpr.
constexpr SFoo foo2(foo); // base copy constructor is constexpr.
constexpr SBar bar(foo); // (line 54): this line fails.
用...编译
clang++ -std=c++1z -c -o test.o test.cpp
产量
test.cpp:54:16: error: constexpr variable 'bar' must be initialized by a constant expression
constexpr SBar bar(foo);
^~~~~~~~
1 error generated.
但是,如果我没有定义USE_ARRAY,一切都有效。
有谁知道为什么会这样?
(我知道std :: array可以提供帮助,但我宁愿使用本机数组并理解底层问题)。
所以对于clang来说,看起来有一些修复方法。 你可以改变:
constexpr SBar(SFoo foo) : SFoo(foo) {}
通过const引用获取foo
:
constexpr SBar(const SFoo &info) : SFoo(info) {}
似乎有效的另一个修复是注释掉sFoo中的以下复制构造函数:
//constexpr SFoo(SFoo &) =default;
我没有立即看到C ++ 1z标准草案中的语言使这一变化有意义。
另一方面,gcc抱怨复制构造函数说隐式定义不是constexpr( 请参见实时 ),例如:
error: explicitly defaulted function 'constexpr SFoo& SFoo::operator=(const SFoo&)' cannot be declared as constexpr because the implicit declaration is not constexpr
constexpr SFoo& operator = (SFoo const&) =default;
^
在我阅读7.1.5
[dcl.constexpr]和5.20
[expr.const]时 ,这对我来说并不明显。
据我在阅读第12.8p26节时可以看出,隐式定义的复制/移动分配应该是constexpr。 所以gcc在这里似乎不正确。
这不是由于阵列成员。 这是由于赋值运算符。 如果进行以下更改,代码将适用于CLANG和GCC:
struct SFoo {
constexpr SFoo() = default;
constexpr SFoo(SFoo const&) = default;
constexpr SFoo(SFoo&&) = default;
constexpr SFoo(int const (&array)[1]) : M_array{array[0]} {}
int M_array[1] = {0};
};
struct SBar : SFoo {
constexpr SBar() = default;
constexpr SBar(SBar const&) = default;
constexpr SBar(SBar&&) = default;
constexpr SBar(SFoo info) : SFoo(info) {}
};
如果您使用std::array
而不是经典数组,那么您之前的设置将起作用:
struct SFoo {
constexpr SFoo() = default;
constexpr SFoo(SFoo const&) = default;
constexpr SFoo(SFoo &) = default;
constexpr SFoo(SFoo &&) = default;
constexpr SFoo& operator = (SFoo const&) = default;
constexpr SFoo& operator = (SFoo &) = default;
constexpr SFoo& operator = (SFoo &&) = default;
constexpr SFoo(std::array<int, 1> const &array) : M_array{array} {}
std::array<int, 1> M_array = {};
};
没有原因。 我还在寻找......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.