在他的演讲中,现代模板元编程:概要第一部分,Walter Brown用他的方式讨论了enable_if与SFINAE的互动。
在谈话中大约47:40,他被问到一个问题,我不能完全匹配他对所提问题的回答。然而,它的关键在于他说SFINAE与过载分辨率分开,恰好在函数的重载分辨率中常用。
我理解他的答案的方式是他也说SFINAE有另一种用途。
在超载解决之外还可以应用SFINAE吗?在听到他对这个问题的回答之前,我的理解是它的仅使用了重载决策。
答案 0 :(得分:1)
如果您认为合适,可以根据参数禁用任何模板。
例如,可以想象矩阵类只能用算术类型实例化。也就是说,我们想要允许实数和整数的矩阵,而不是字符串。你可以这样做:
#include <type_traits>
template<typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
class Matrix
{
// ...
};
现在,如果用户执行Matrix<double> m {}
,它将会愉快地编译,但是Matrix<std::string>
会给出一个简单的错误消息,即未定义此类型。这可能会帮助用户多于错误消息的页面,而矩阵类的某些内部结构不会产生std::string
个操作数的有效代码。
另一个用例是在模板的部分特化中进行选择。这可能是一个愚蠢的例子,但它可能会给你一个想法。假设我们有一个模板,它接受两个类型参数,并希望专注于它们都引用相同类型的情况。但是,如果类型小于int
,则专业化(由于某些不明原因)比主模板更差,因此在这种情况下我们不希望它。
#include <iostream>
#include <type_traits>
template<typename T1, typename T2>
struct X
{
void
operator()()
{
std::cout << "I'm the primary template." << std::endl;
}
};
template<typename T>
struct X<T, typename std::enable_if<(sizeof(T) >= sizeof(int)), T>::type>
{
void
operator()()
{
std::cout << "I'm the partial specialization." << std::endl;
}
};
int
main()
{
X<int, float> int_float {}; // primary template
X<int, int> int_int {}; // partial specialization
X<char, char> char_char {}; // primary template!
int_float();
int_int();
char_char();
}
我的系统输出:
I'm the primary template.
I'm the partial specialization.
I'm the primary template.