我从cppreference得到了c++概念move_constructible
的以下实现
template<typename _Tp>
concept move_constructible =
constructible_from<_Tp, _Tp> &&
convertible_to<_Tp, _Tp>;
字符串
我不明白这为什么有用。我假设任何类型都可以转换为自身,所以第二个要求是毫无意义的(上帝,我一定是在某些方面错得很离谱)。另外,对于第一个要求,我希望像constructible_from<_Tp, _Tp&&>
这样的东西来检查类型是否可以从rvalue-ref构造(因此,移动)。
请解释一下这个实现是如何工作的。
1条答案
按热度按时间4si2a6ki1#
大多数traits/concept会自动将
&&
添加到“源”参数的类型中(传递给函数的东西,如std::is_invocable
,或从函数构造的东西,如std::is_constructible
)。即
constructible_from<A, B>
等价于constructible_from<A, B &&>
(&&
会自动添加到第二个参数中,但不会添加到第一个参数中),convertible_to<A, B>
等价于convertible_to<A &&, B>
。请注意,如果一个类型已经包含
&
,则向其添加&&
没有任何效果。因此,虽然T
和T &&
在这里是等价的,但T &
不是。这可以从那些以
std::declval<T>()
定义的trait/概念中推断出来,它返回T &&
。关于
std::declval<T &>()
返回T &
的原因,请参阅reference collapsing。**注:**有一个例外:将一个不完整的类型(例如一个声明但未定义的类)作为非第一个参数传递给
is_constructible
(和constructible_from
)是UB,一些编译器会拒绝它。手动追加&&
可以绕过这条规则,因此在泛型代码中,您应该始终首选将T &&
传递给这些traits。但是对于
move_constructible
来说没有区别,因为它首先对不完整类型没有意义。