我对如何在下面的示例中进行模板参数推断感到困惑。我在本文的其余部分使用术语 调用 来暗示 实例化并调用 。
我将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;
}
输出:
Execute 'auto b = std::move(a);'
Execute 'auto c = std::move(static_cast<my_type&&>(a));'
Invoke std::move() specialization
答案 0 :(得分:5)
当您致电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));
)
这是因为generic definition看起来像这样:
template< class T >
constexpr typename std::remove_reference<T>::type&& move( T&& t );
T&&
是关键。在类型推导的上下文中,它可以绑定到my_type&
,my_type&&
或任何cv(const
或volatile
)变体。这就是为什么在没有专业化的情况下,它能够为两个调用调用通用版本。
因此,要真正覆盖所有基础,您需要多个重载。但是,对于你的类型约束custom_move
,你可能会更好。
答案 1 :(得分:1)
所以,你的第一个问题是(bool IsDivisibleBy3, bool IsDivisibleBy5) match = (i % 3 == 0, i % 5 == 0);
switch (match)
{
case var _ when match.IsDivisibleBy3 && match.IsDivisibleBy5:
// FizzBuzz
break;
case var _ when match.IsDivisibleBy3:
// Fizz
break;
case var _ when match.IsDivisibleBy5:
// Buzz
break;
default:
//
break;
}
中任何事物的专业化都必须遵守你所专注的事物的要求。这意味着......你不能做任何不同的事情。
其次,std
的通用版本使用完美转发。专业化不能。
std::move
应该这样做。
这是一个糟糕的计划。