以下摘录使用Clang-libstdc ++或Clang-libc ++,GCC,它们的许多版本以及该语言自11(14&17)以来的所有三个版本进行编译:
#include <type_traits>
struct HasUserDefinedDestructor {
~HasUserDefinedDestructor() {}
};
using HUDD = HasUserDefinedDestructor;
static_assert(not std::is_trivially_move_constructible<HUDD>::value, "");
static_assert(not std::is_trivially_copy_constructible<HUDD>::value, "");
这使我感到惊讶,因为复制仅需要微不足道的操作。
这是编译器/库中的错误吗,还是标准在某个地方说用户定义了析构函数会使复制和移动构造函数变得不那么琐碎?
编辑:为什么这不是默认构造问题的重复: 根据注释,我们知道构造函数的“异常”和琐碎性受到析构函数的异常和琐碎性的影响,但是在知道所有这些特征都相关之前,问题是不同的。遇到这个问题,任何人都可以看到这与之相关
答案 0 :(得分:1)
is_trivially_constructible
是defined as follows(粗体是我的):
is_constructible_v<T,Args...>
为true
,并且is_constructible
的变量定义(如下定义)已知不会调用不平凡的操作
«在下面定义»是[meta.unary.op]/8:
当且仅当对于某些发明变量
is_constructible<T, Args...>
遵循以下变量定义时,才应满足模板专业化t
的谓词条件:
T t(declval<Args>()...);
是的,当析构函数不是很简单时,is_trivially_[copy|move]_constructible_v
是false
。
答案 1 :(得分:1)
[...]如果函数是由用户声明而不是显式的,则由用户提供 在其第一个声明中默认或删除。 [...]
因此,给定
struct HasUserDefinedDestructor {
~HasUserDefinedDestructor() {}
};
HasUserDefinedDestructor
具有用户提供的析构函数。
如果不是用户提供的析构函数,并且如果:[...]
否则,析构函数是不平凡的。
因此,HasUserDefinedDestructor
具有不平凡的析构函数。
template <class T, class... Args> struct is_trivially_constructible;
条件:
is_constructible_v<T, Args...>
是true
,is_constructible
的变量定义如下所述,是 已知会调用不重要的操作([basic.types, [特殊]。前提条件:
T
,并且参数包Args
中的所有类型均应为完整类型 cvvoid
,或未知范围的数组。template <class T> struct is_trivially_copy_constructible;
条件:对于可引用类型
T
,结果与is_trivially_constructible_v<T, const T&>
相同,否则为false
。前提条件:
T
应该是完整类型cv void
或未知边界数组。template <class T> struct is_trivially_move_constructible;
条件:对于可引用类型
T
,结果与is_trivially_constructible_v<T, T&&>
相同,否则为false
。前提条件:
T
应该是完整类型cv void
或未知边界数组。
模板专门化的谓词条件
is_constructible<T, Args...>
在且仅当 以下变量定义对于某些已发明的格式将是正确的 变量t
:T t(declval<Args>()...);
[注意:”这些标记从不解释为函数 宣言。 — 尾注]就像执行访问检查一样 与
T
和任何Args
不相关的上下文中。只有有效性 考虑变量初始化的即时上下文。 [注意:初始化的评估可能会导致 效果,例如类模板专业化的实例化 和功能模板专业化, 隐式定义的函数,等等。这样的副作用不在 “即时上下文”,并可能导致程序被 格式错误。 — 尾注]
即使似乎在定义位置未调用析构函数,也应该使用变量定义“调用”析构函数。因此,std::is_trivially_move_constructible<HUDD>::value
和false
都是std::is_trivially_copy_constructible<HUDD>::value
。