LWG 2424 讨论了原子,互斥和条件变量的不良状态 平凡的可复制 在C ++中14。我很感激修复 已经排队了但是 std::mutex
, std::condition variable
等。似乎有非平凡的析构函数。例如:
30.4.1.2.1类互斥[thread.mutex.class]
namespace std {
class mutex {
public:
constexpr mutex() noexcept;
~mutex(); // user-provided => non-trivial
…
}
}
这不应该取消他们可以轻易复制的资格吗?
要么是我的错,要么我被错误引用,我老实说不记得是哪一个。
但是,我对这个主题有非常强烈的建议:
不使用 is_trivial
也不 is_trivially_copyable
! EVER !!!
而是使用以下其中一个:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
理由:
tldr: 看到这个 优秀的问题和正确的答案。
没有人(包括我自己)能记住这个定义 is_trivial
和 is_trivially_copyable
。如果你确实碰巧查了一下,然后花了10分钟来分析它,它可能会也可能不会做你直觉认为它做的事情。如果您设法正确分析它,CWG很可能会在很少或没有通知的情况下更改其定义并使您的代码无效。
运用 is_trivial
和 is_trivially_copyable
正在玩火。
但是这些:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
完全按照他们的意思行事,并且不太可能改变他们的定义。必须单独处理每个特殊成员似乎过于冗长。但它会为您的代码的稳定性/可靠性带来回报。如果必须,将这些个性特征打包成自定义特征。
更新
例如,clang&gcc编译这个程序:
#include <type_traits>
template <class T>
void
test()
{
using namespace std;
static_assert(!is_trivial<T>{}, "");
static_assert( is_trivially_copyable<T>{}, "");
static_assert( is_trivially_destructible<T>{}, "");
static_assert( is_destructible<T>{}, "");
static_assert(!is_trivially_default_constructible<T>{}, "");
static_assert(!is_trivially_copy_constructible<T>{}, "");
static_assert( is_trivially_copy_assignable<T>{}, "");
static_assert(!is_trivially_move_constructible<T>{}, "");
static_assert( is_trivially_move_assignable<T>{}, "");
}
struct X
{
X(const X&) = delete;
};
int
main()
{
test<X>();
}
注意 X
是 可以轻易复制,但是 不 简单地复制可构造的。据我所知,这是一致的行为。
VS-2015目前表示 X
是 也不 平凡的可复制的,也不是简单的复制可构造的。根据目前的规格,我认为这是错误的,但它肯定符合我的常识告诉我的。
如果我需要 memcpy
至 未初始化 记忆,我相信 is_trivially_copy_constructible
过度 is_trivially_copyable
向我保证这样的操作会没问题。如果我想 memcpy
至 初始化 记忆,我会检查 is_trivially_copy_assignable
。