Sou*_*Roy 2 c++ stl template-specialization move-semantics c++11
我对如何在下面的例子中进行模板参数推断感到困惑.我在本文的其余部分使用术语invoke来暗示实例化和调用.
我专注std::move()于我的自定义类型my_type,我观察到,对于x类型的实例my_type:
std::move(x) 继续调用通用模板std::move(static_cast<my_type&&>(x))或std::move(std::forward(x))调用专业化我的问题是:
这是整个代码:
#include<iostream>
#include<utility>
struct my_type
{
int x;
};
namespace std
{
// This is the std::move() definition in the preprocessor output:
//
// template <class _Tp>
// inline __attribute__ ((__visibility__("hidden"), __always_inline__)) constexpr
// typename remove_reference<_Tp>::type&&
// move(_Tp&& __t) noexcept
// {
// typedef typename remove_reference<_Tp>::type _Up;
// return static_cast<_Up&&>(__t);
// }
// This is std::move() specialized for my_type
template<>
inline
typename std::remove_reference<my_type>::type&&
move<my_type>(my_type&& t) noexcept
{
std::cout << "Invoke std::move() specialization\n";
return static_cast<typename remove_reference<my_type>::type&&>(t);
}
} // namespace std
int main()
{
auto a = my_type();
std::cout << "Execute 'auto b = std::move(a);'\n";
auto b = std::move(a); // Invokes the generic template
std::cout << "Execute 'auto c = std::move(static_cast<my_type&&>(a));'\n";
auto c = std::move(static_cast<my_type&&>(a)); // Invokes the specialization
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Execute 'auto b = std::move(a);'
Execute 'auto c = std::move(static_cast<my_type&&>(a));'
Invoke std::move() specialization
Run Code Online (Sandbox Code Playgroud)
当你调用is std::move(a)的类型时,不是.因此,泛型是更好的匹配,因为它可以完全匹配.amy_type&my_type&&std::move
如果您将重载更改move为如下所示:
inline
typename std::remove_reference<my_type>::type&&
move(my_type& t) noexcept
{
std::cout << "Invoke std::move() specialization\n";
return static_cast<typename remove_reference<my_type>::type&&>(t);
}
Run Code Online (Sandbox Code Playgroud)
然后它将被适当地调用(但通用的将被调用std::move(static_cast<my_type&&>(a));)
发生这种情况是因为通用定义如下所示:
template< class T >
constexpr typename std::remove_reference<T>::type&& move( T&& t );
Run Code Online (Sandbox Code Playgroud)
这T&&是关键.在型扣的上下文中其可以结合到二者my_type&,my_type&&或任何CV(const或volatile)的变化.这就是为什么在没有专业化的情况下,它能够为两个调用调用通用版本.
因此,要真正覆盖所有基础,您将需要多个重载.但是,你可能会custom_move因为你的类型受到限制而变得更好.