[英]Invoking specialized std::move()
我對以下示例中如何進行模板自變量推導感到困惑。 在本文的其余部分中,我將使用術語“ 調用 ”來表示實例化和invoke 。
我為我的自定義類型my_type
專門化了std::move()
,並觀察到對於my_type
類型的實例x
:
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;
}
輸出:
Execute 'auto b = std::move(a);'
Execute 'auto c = std::move(static_cast<my_type&&>(a));'
Invoke std::move() specialization
當您調用std::move(a)
, a
的類型為my_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);
}
然后將適當地調用它(但通用的將被要求std::move(static_cast<my_type&&>(a));
)
發生這種情況是因為通用定義如下所示:
template< class T >
constexpr typename std::remove_reference<T>::type&& move( T&& t );
T&&
是關鍵。 在類型推導的上下文中,它可以綁定到my_type&
, my_type&&
或任何cv( const
或volatile
)變體。 這就是為什么在沒有專業化的情況下它能夠為兩個調用調用通用版本的原因。
因此,要真正覆蓋所有基礎,您將需要多個重載。 不過,也許,為您的類型設置一個custom_move
會更好。
因此,您的第一個問題是std
中任何事物的專業化都必須遵守您正在專門化的事物的要求。 這意味着...您不得做任何其他事情。
其次, std::move
的通用版本使用完美的轉發。 專業不能。
#define SPEC_MOVE(X) \
template<> inline \
typename std::remove_reference<X>::type&& move<X>(X t) noexcept \
{ \
std::cout << "Invoke std::move() specialization\n"; \
return static_cast<typename remove_reference<X>::type&&>(t); \
}
SPEC_MOVE(my_type&&)
SPEC_MOVE(my_type&)
SPEC_MOVE(my_type const&)
SPEC_MOVE(my_type const&&)
SPEC_MOVE(my_type const volatile&&)
SPEC_MOVE(my_type const volatile&)
SPEC_MOVE(my_type volatile&)
SPEC_MOVE(my_type volatile&&)
那應該做。
這是一個壞計划。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.