调用专用 std::move()
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))
调用专业化 - 在没有我的专业化的情况下,上述所有调用都会调用通用模板
我的问题是:
- 为什么上面项目 #1 中的调用不调用专业化?
- 在没有专业化的情况下,项目 #1 和 #2 中的调用如何表现相同?
以下是整个代码:
#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() specializationn";
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() specializationn";
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() specializationn";
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&&)
这应该可以做到。
这是一个糟糕的计划。
相关文章:
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 复制elision、std::move和链式函数调用
- 为什么我的代码中没有调用move构造函数
- 如何调用move构造函数
- 复制初始化:为什么即使关闭了复制省略,也没有调用move或copy构造函数
- 调用了Copy ctor而不是move ctor
- 基于范围的 std::move 调用意外复制构造函数
- 编译器发射std :: move()运行时调用
- 为什么编译器在调用 move 后选择复制 ctor
- 调用专用 std::move()
- 在智能指针的反引用值上调用 std::move()
- Move-CTOR和COPY-CTOR未调用
- 为什么noexcept move构造函数在向量重新分配期间没有被调用
- 为什么 std::move 未定义,尽管编译器使用 -std=c++11 调用
- 反复调用MOVE,其中需要RVALUE参考
- 警告在 std::move'ing 时调用复制 ctor
- 如何在基类中调用 "move" '&&' 构造函数?在C++
- move构造函数在C++中调用了两次吗
- 与move构造函数配对时,会发生意外的析构函数调用
- 为move调用转换构造函数,但未为copy调用转换构造函数