问题描述
我写了以下代码:
#include <iostream>
#include <string>
#include <type_traits>
template<typename, typename = void>
struct is_incrementable : std::false_type {};
template<typename T>
struct is_incrementable<T, decltype( ++std::declval<T&>() )> : std::true_type {};
int main()
{
std::cout << is_incrementable<std::string>::value << std::endl;
std::cout << is_incrementable<int>::value << std::endl;
}
运行它时,我得到 0 0
。但是我希望 0 1
。
When I run it, I get 0 0
. But I expected 0 1
.
有什么想法吗?
推荐答案
对于 std :: string
,选择主要模板并考虑专业化。但是 decltype(++ std :: declval< T&>())
格式不正确,因此不被考虑,并且它是主要模板(非专用模板)使用,结果为 0
。
For std::string
, the primary template is chosen and the specialization is considered. But decltype(++std::declval<T&>())
is ill-formed, so it is not considered and the primary template (non-specialized template) is used, which results in 0
.
如果使用 int
,它变得更加复杂。编译器一如既往地选择主模板,然后考虑专业化(这是因为始终认为专业化是更好的匹配)。特殊化是 int
的< int,int&>
,但它与非专业化的匹配模板< int,void>
( void
是默认模板参数),因此将忽略专业化
If you use int
, it gets a bit more complicated. The primary template gets chosen by the compiler, as always, and then the specialization is considered (that's because specialization are always considered better matches). The specialization is <int, int&>
for int
, but it doesn't match the non-specialized template <int, void>
(the void
is the default template argument), so the specialization is ignored because it doesn't match.
因此,默认模板参数的类型必须匹配,否则将不考虑专业化,因为仅当每个模板参数匹配特化。
So, the types of default template parameter have to match, or else the specialization is not taken into account, as a specialization is only taken when every template argument matches the specialization.
只需在末尾附加 void()
即可使特化匹配第二个模板参数,因为左侧的表达式被舍弃并且 void()
的类型为 void
,与主变量匹配模板的第二个模板参数。
Just append a void()
at the end to make the specialization match for the second template parameter, as the left expression is discarded and the type of void()
is void
, which matches the primary template's second template parameter.
template<typename T>
struct is_incrementable<T, decltype( ++std::declval<T&>(), void() )> : std::true_type {};
在C ++ 17中,您将使用。
In C++17, you would use std::void_t
for that.
这篇关于为什么不选择模板专业化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!