C++ 在constexpr中使用普通复制/移动可分配并集时发生冲突
考虑到以下代码C++ 在constexpr中使用普通复制/移动可分配并集时发生冲突,c++,c++11,clang,c++14,constexpr,C++,C++11,Clang,C++14,Constexpr,考虑到以下代码 struct S { constexpr S() = default; constexpr S(S const &) = default; constexpr S(S &) = default; constexpr S(S &&) = default; #if 1 S & operator = (S const &) = default; S & operator = (S &
struct S
{
constexpr S() = default;
constexpr S(S const &) = default;
constexpr S(S &) = default;
constexpr S(S &&) = default;
#if 1
S & operator = (S const &) = default;
S & operator = (S &) = default;
S & operator = (S &&) = default;
#else
constexpr S & operator = (S const &) = default;
constexpr S & operator = (S &) = default;
constexpr S & operator = (S &&) = default;
#endif
~S() = default;
};
struct U
{
union
{
S s;
};
constexpr U() : s{} { ; }
};
inline constexpr bool test()
{
U v;
U w;
v = w;
return true;
}
static_assert(test());
我发现有矛盾
我想在constexpr
中使用union
(或类似union的类)
版本#如果1
给出错误(错误:constexpr函数从不生成常量表达式
):
但是版本#如果0
也会给出一个错误(错误:复制赋值运算符的默认定义不是constexpr
):
以上所有内容适用于clang3.7.0版本
,但较新版本的clang3.8.0(主干253951)
没有说明constepr S&operator=(S const&)=default代码>(它允许编译这样的代码),但结果是一样的
对于简单的复制/移动构造函数,但用户提供的赋值运算符类似的代码(构造)编译起来很好
我认为问题(bug)在于用户声明的特殊函数,但它应该是合法的
另外,请看合同的最后一条和最后一条。在我看来,由于编译器对下一个定义的解释不同,设计得相当好的变体在constexpr
中变得毫无用处:
struct S {};
以及:
但在我看来,两者都是等价的(编译器认为第二个不是POD,但谁在乎呢?)
为什么空struct
的默认赋值运算符不是constexpr
更新:
删除析构函数声明会使问题消失。因此,即使是用户声明的(非用户提供的)析构函数也会使隐式定义的默认赋值运算符不被标记为constexpr
,并且是非平凡的。这肯定是错误的,因为没有人告诉我这一点。在开发过程中,我意识到clang
的联合部分和
libc++
的部分测试非常差。gcc/clang同意constepr
赋值是错误的,但当它未标记为constexpr
时,他们不同意:
main.cpp:12:5: error: defaulted definition of copy assignment operator is not constexpr
constexpr S & operator = (S const &) = default;
^
main.cpp:13:5: error: defaulted definition of copy assignment operator is not constexpr
constexpr S & operator = (S &) = default;
^
main.cpp:14:5: error: defaulted definition of move assignment operator is not constexpr
constexpr S & operator = (S &&) = default;
^
main.cpp:35:7: error: object of type 'U' cannot be assigned because its copy assignment operator is implicitly deleted
v = w;
^
main.cpp:24:11: note: copy assignment operator of 'U' is implicitly deleted because field 's' has no copy assignment operator
S s;
^
4 errors generated.
struct S {};
struct S
{
constexpr S() = default;
constexpr S(S const &) = default;
constexpr S(S &) = default;
constexpr S(S &&) = default;
S & operator = (S const &) = default;
S & operator = (S &) = default;
S & operator = (S &&) = default;
~S() = default;
};