理解 C++ move_constructible 概念实现

Del*_*ltA 7 c++ move-constructor move-semantics c++-concepts c++20

move_constructible我从cppreference得到了以下 C++ 概念的实现

template<typename _Tp>
concept move_constructible =
    constructible_from<_Tp, _Tp> &&
    convertible_to<_Tp, _Tp>;
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这有效。我认为任何类型都可以转换为自身,因此第二个要求是毫无意义的(上帝,我一定是在某些方面错了)。另外,对于第一个要求,我希望constructible_from<_Tp, _Tp&&>检查类型是否可以从 rvalue-ref 构造(因此移动)。

请解释一下这个实现是如何工作的。

Hol*_*Cat 5

大多数特征/概念会自动添加&&到“源”参数的类型(传递给函数的东西,如 中std::is_invocable,或构造自,如std::is_constructible)。

Ieconstructible_from<A, B>相当于constructible_from<A, B &&>(&&自动添加到第二个参数,但不添加到第一个),并且convertible_to<A, B>相当于convertible_to<A &&, B>.

请注意,如果类型已包含&,则添加&&到该类型中不会产生任何效果。因此,虽然TT &&在这里是等价的,T &但不是。


这可以从那些根据 定义的特征/概念推断出来std::declval<T>(),它返回T &&

std::declval<T &>()关于返回的原因T &,请参阅参考崩溃


注意:有一个例外:将不完整类型(例如已声明但未定义的类)作为非第一个参数传递给is_constructible(and constructible_from) 是 UB,并且某些编译器会拒绝它。手动附加&&可以绕过此规则,因此在通用代码中,您应该始终更喜欢传递T &&这些特征。

但具体来说move_constructible没有什么区别,因为它首先对于不完整的类型来说是没有意义的。

  • 为什么需要“convertible_to”和“constructible_from”? (2认同)