首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用专用std::move()

调用专用std::move()
EN

Stack Overflow用户
提问于 2017-05-10 22:30:30
回答 2查看 244关注 0票数 3

在下面的示例中,我对模板参数推断是如何发生的感到困惑。在本文的其余部分中,我使用了术语invoke来暗示实例化和调用

我为我的自定义类型std::move()专门化了my_type,并且我观察到,对于my_type类型的x

  1. std::move(x)继续调用泛型模板
  2. std::move(static_cast<my_type&&>(x))std::move(std::forward(x))调用专门化
  3. 在没有专门化的情况下,上述所有调用都调用泛型模板。

我的问题是:

  • 为什么上面第1项中的调用不调用专门化?
  • 在没有专门化的情况下,第1项和第2项中的调用行为如何?

以下是整个代码:

代码语言:javascript
复制
#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;
}

输出:

代码语言:javascript
复制
Execute 'auto b = std::move(a);'
Execute 'auto c = std::move(static_cast<my_type&&>(a));'
Invoke std::move() specialization
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-10 22:43:48

当您调用std::move(a)时,a的类型是my_type&,而不是my_type&&。因此,泛型std::move是一个更好的匹配,因为它可以准确匹配。

如果您将move重载更改为如下所示:

代码语言:javascript
复制
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));)

之所以会出现这种情况,是因为泛型定义看起来如下:

代码语言:javascript
复制
template< class T >
constexpr typename std::remove_reference<T>::type&& move( T&& t );

T&&是关键。在类型推断的上下文中,它可以绑定到my_type&my_type&&或任何cv (constvolatile)变体。这就是为什么在没有专门化的情况下,它能够为两个调用调用通用版本。

因此,要真正覆盖所有的基地,你需要一个以上的过载。尽管如此,您最好还是使用custom_move来限制您的类型。

票数 6
EN

Stack Overflow用户

发布于 2017-05-10 23:27:56

因此,您的第一个问题是,std中的任何事物的专门化都必须服从您所专门处理的事物的要求。也就是说..。你不能做任何不同的事。

第二,通用版本的std::move使用完美的转发。专门性不能。

代码语言:javascript
复制
#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&&)

这样就行了。

这是个糟糕的计划。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43903698

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档