考虑以下代码:
template <typename T>
struct dependent_type
{
using type = T;
};
template <typename T>
auto foo(T) -> std::enable_if_t<std::is_same<T, int>{}>
{
std::cout << "a\n";
}
template<typename T>
void foo(typename dependent_type<T>::type)
{
std::cout << "b\n";
}
foo
can的第一个重载可以T
从其调用中得出。
的第二过载foo
是一个非推测的上下文。
int main()
{
foo<int>( 1 ); // prints "b"
foo<double>( 1.0 ); // prints "b"
foo( 1 ); // prints "a"
}
为什么foo<int>( 1 )
打印“ b”而不打印“ a”?
本质上,部分排序规则说,dependent_type
由于该非推论上下文,重载更加专业化。
模板功能排序的过程基于变换模板功能类型并依次对每种模板执行模板推演,一次是从第一个模板(一个拿走T
)到第二个模板(一个拿走dependent_type
),然后是从第二个到第一个。
这些规则太过复杂而无法在此处复制,但是[temp.func.order]
如果您需要血腥的细节,请阅读并阅读其链接的段落。这是一个快速的简化:
对于模板函数的每个模板参数,组成一个唯一的类型,然后用该类型替换参数。此示例的转换类型为:
void foo(UniqueType); //ignoring the SFINAE for simplicity
void foo(typename dependent_type<UniqueType>::type);
然后,我们在两个方向上执行模板推导:一次使用第一个模板的参数作为第二个模板的参数,一次使用第二个模板的参数作为第一个模板的参数。这类似于对以下函数调用执行推导:
//performed against template <class T> void foo(typename dependent_type<T>::type);
foo(UniqueType{});
//performed against template <class T> void foo(T);
foo(dependent_type<UniqueType>::type{});
在进行这些推论时,我们试图辨别一个过载是否比另一个过载更专业。当我们尝试第一个时,推论失败,因为这typename dependent_type<T>::type
是一个非推论的上下文。对于第二个,推论成功是因为dependent_type<UniqueType>::type
公正UniqueType
,所以T
推论到UniqueType
。
由于推论从第二个模板到第一个模板失败,因此第二个模板被认为比第一个模板更专业。最终结果是,重载分辨率优先选择的第二个模板foo<int>(1)
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句