持有trivially copyable类型的WMutable<T>是否应属trivially copyable?
关于
WMutable<T>是否属于trivially copyable的编译器分歧问题 示例代码如下:
我们定义了4个类:
S<T>:包含一个数据成员。SCtor<T>:包含一个数据成员,且拥有模板构造函数。SCtorMutable<T>:包含一个mutable数据成员,且拥有模板构造函数。SCtorDefault<T>:包含一个成员,拥有模板构造函数,且显式默认了复制/移动构造函数与复制/移动赋值运算符。
所有编译器均判定这4个类为trivially copyable。
若使用普通包装类W<T>持有上述任一类作为数据成员,包装类W<S...<T>>仍会被判定为trivially copyable。
但若使用另一个包装类WMutable<T>持有上述任一类作为mutable数据成员,不同编译器的判定出现分歧:
- MSVC仍判定
WMutable<S...<T>>为trivially copyable。 - clang判定
WMutable<S<T>>为trivially copyable,但WMutable<SCtor...<T>>因非平凡复制构造,不属trivially copyable。 - gcc判定
WMutable<S<T>>为trivially copyable,WMutable<SCtor...<T>>虽非平凡复制构造,但仍属trivially copyable。
那么,WMutable<T>是否应被判定为trivially copyable?
#include <type_traits> #include <utility> template<typename T> struct S { T m_t; }; template<typename T> struct SCtor { T m_t; template<typename... U> SCtor(U&&... u): m_t(std::forward<U>(u)...) {} }; template<typename T> struct SCtorMutable { mutable T m_t; template<typename... U> SCtorMutable(U&&... u): m_t(std::forward<U>(u)...) {} }; template<typename T> struct SCtorDefault { T m_t; template<typename... U> SCtorDefault(U&&... u): m_t(std::forward<U>(u)...) {} SCtorDefault(SCtorDefault const&) = default; SCtorDefault(SCtorDefault&&) = default; SCtorDefault& operator=(SCtorDefault const&) = default; SCtorDefault& operator=(SCtorDefault&&) = default; }; template<typename T> struct W { T m_t; }; template<typename T> struct WMutable { mutable T m_t; }; static_assert(std::is_trivially_copyable<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_trivially_copy_assignable<S<int>>::value); static_assert(std::is_trivially_move_assignable<S<int>>::value); static_assert(std::is_trivially_copyable<SCtor<int>>::value); static_assert(std::is_trivially_copy_constructible<SCtor<int>>::value); static_assert(std::is_trivially_move_constructible<SCtor<int>>::value); static_assert(std::is_trivially_copy_assignable<SCtor<int>>::value); static_assert(std::is_trivially_move_assignable<SCtor<int>>::value); static_assert(std::is_trivially_copyable<SCtorMutable<int>>::value); static_assert(std::is_trivially_copy_constructible<SCtorMutable<int>>::value); static_assert(std::is_trivially_move_constructible<SCtorMutable<int>>::value); static_assert(std::is_trivially_copy_assignable<SCtorMutable<int>>::value); static_assert(std::is_trivially_move_assignable<SCtorMutable<int>>::value); static_assert(std::is_trivially_copyable<SCtorDefault<int>>::value); static_assert(std::is_trivially_copy_constructible<SCtorDefault<int>>::value); static_assert(std::is_trivially_move_constructible<SCtorDefault<int>>::value); static_assert(std::is_trivially_copy_assignable<SCtorDefault<int>>::value); static_assert(std::is_trivially_move_assignable<SCtorDefault<int>>::value); static_assert(std::is_trivially_copyable<W<S<int>>>::value); static_assert(std::is_trivially_copy_constructible<W<S<int>>>::value); static_assert(std::is_trivially_move_constructible<W<S<int>>>::value); static_assert(std::is_trivially_copy_assignable<W<S<int>>>::value); static_assert(std::is_trivially_move_assignable<W<S<int>>>::value); static_assert(std::is_trivially_copyable<W<SCtor<int>>>::value); static_assert(std::is_trivially_copy_constructible<W<SCtor<int>>>::value); static_assert(std::is_trivially_move_constructible<W<SCtor<int>>>::value); static_assert(std::is_trivially_copy_assignable<W<SCtor<int>>>::value); static_assert(std::is_trivially_move_assignable<W<SCtor<int>>>::value); static_assert(std::is_trivially_copyable<W<SCtorMutable<int>>>::value); static_assert(std::is_trivially_copy_constructible<W<SCtorMutable<int>>>::value); static_assert(std::is_trivially_move_constructible<W<SCtorMutable<int>>>::value); static_assert(std::is_trivially_copy_assignable<W<SCtorMutable<int>>>::value); static_assert(std::is_trivially_move_assignable<W<SCtorMutable<int>>>::value); static_assert(std::is_trivially_copyable<W<SCtorDefault<int>>>::value); static_assert(std::is_trivially_copy_constructible<W<SCtorDefault<int>>>::value); static_assert(std::is_trivially_move_constructible<W<SCtorDefault<int>>>::value); static_assert(std::is_trivially_copy_assignable<W<SCtorDefault<int>>>::value); static_assert(std::is_trivially_move_assignable<W<SCtorDefault<int>>>::value); static_assert(std::is_trivially_copyable<WMutable<S<int>>>::value); static_assert(std::is_trivially_copy_constructible<WMutable<S<int>>>::value); static_assert(std::is_trivially_move_constructible<WMutable<S<int>>>::value); static_assert(std::is_trivially_copy_assignable<WMutable<S<int>>>::value); static_assert(std::is_trivially_move_assignable<WMutable<S<int>>>::value); static_assert(std::is_trivially_copyable<WMutable<SCtor<int>>>::value); // clang下报错 static_assert(std::is_trivially_copy_constructible<WMutable<SCtor<int>>>::value); // clang/gcc下报错 static_assert(std::is_trivially_move_constructible<WMutable<SCtor<int>>>::value); static_assert(std::is_trivially_copy_assignable<WMutable<SCtor<int>>>::value); static_assert(std::is_trivially_move_assignable<WMutable<SCtor<int>>>::value); static_assert(std::is_trivially_copyable<WMutable<SCtorMutable<int>>>::value); // clang下报错 static_assert(std::is_trivially_copy_constructible<WMutable<SCtorMutable<int>>>::value); // clang/gcc下报错 static_assert(std::is_trivially_move_constructible<WMutable<SCtorMutable<int>>>::value); static_assert(std::is_trivially_copy_assignable<WMutable<SCtorMutable<int>>>::value); static_assert(std::is_trivially_move_assignable<WMutable<SCtorMutable<int>>>::value); static_assert(std::is_trivially_copyable<WMutable<SCtorDefault<int>>>::value); // clang下报错 static_assert(std::is_trivially_copy_constructible<WMutable<SCtorDefault<int>>>::value); // clang/gcc下报错 static_assert(std::is_trivially_move_constructible<WMutable<SCtorDefault<int>>>::value); static_assert(std::is_trivially_copy_assignable<WMutable<SCtorDefault<int>>>::value); static_assert(std::is_trivially_move_assignable<WMutable<SCtorDefault<int>>>::value);
内容的提问来源于stack exchange,提问作者wanghan02
相关产品推荐
相关产品推荐

