示例代码如下或godbolt。clang 16/trunk认为S<int>
不是trivially_copyable
类。clang 15、gcc trunk和MSVC则不这么认为。
#include <type_traits>
template<typename T>
struct S {
T m_t;
S(S const&) = default;
S(S&&) = default;
S& operator=(S const&) requires (!std::is_integral<T>::value) = default;
~S() = default;
};
// next five assertions pass for all compilers
static_assert(std::is_trivially_destructible<S<int>>::value);
static_assert(std::is_trivially_copy_constructible<S<int>>::value);
static_assert(std::is_trivially_move_constructible<S<int>>::value);
static_assert(!std::is_copy_assignable<S<int>>::value);
static_assert(!std::is_move_assignable<S<int>>::value);
// compiles with gcc trunk, MSVC and clang 15, fails with clang 16/trunk
static_assert(std::is_trivially_copyable<S<int>>::value);
根据标准的class.prop:
普通可复制类是一个类:
- 具有至少一个合格的复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符([special],
[class.copy.ctor],[class.copy.assign]),
- 其中每个合格的复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符都是平凡的,并且
- 它有一个平凡的、未删除的析构函数([class.dtor])。
S<int>
有平凡的复制/移动构造函数和平凡的析构函数。其复制/移动分配运算符不合格。我同意gcc/MSVC/clang 15的观点。是clang 16/trunk在这一个上错了还是我错过了什么?
编辑:这是一个确认的clang bug。
1条答案
按热度按时间93ze6v8z1#
是的,
S<int>
是可复制的。看起来你发现了一个叮当虫。我无法找到它在:这可能是一个新的回归。
S<int>
可平凡复制的证明值得一提的是,* elecible * 是什么意思:
合格的特殊成员函数是满足以下条件的特殊成员函数:
*相关的约束([temp.constr])(如果有的话)被满足,并且
此复制赋值运算符是用户声明的(而不是用户提供的),并且不满足其约束,因此它是不合格的。此外:
如果类
X
的定义没有显式声明移动赋值运算符,则当且仅当X
没有用户声明的复制构造函数,这意味着:
所有剩余的(合格的)特殊成员函数都是平凡的,因此
S<int>
是平凡可复制的。