SFINAE 在重载决议之外?
SFINAE outside of overload resolution?
在他的演讲现代模板元编程:纲要第 I 部分中,Walter Brown 以他的方式讨论 enable_if 与 SFINAE 的交互。
在大约 47:40 的谈话中,他被问到一个问题,我无法完全匹配他对所问问题的回答。然而,问题的症结似乎在于他是在说 SFINAE 独立于重载解析,恰好常用于函数的重载解析。
我理解他的回答的方式是他也在说SFINAE还有另一个用途。
除了重载解析之外,SFINAE 还能应用到哪些地方?在听到他对这个问题的回答之前,我的理解是它唯一的用途是重载解析。
如果您认为合适,您可以根据参数禁用任何模板。
例如,可以想象一个矩阵 class 应该只用算术类型实例化。也就是说,我们希望允许实数和整数矩阵而不是字符串矩阵。你可以这样做:
#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>
会给出一个简单的错误消息,指出没有定义这种类型。这可能会帮助用户提供超过页面的错误消息,即矩阵 class 的某些内部结构没有为 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.
在他的演讲现代模板元编程:纲要第 I 部分中,Walter Brown 以他的方式讨论 enable_if 与 SFINAE 的交互。
在大约 47:40 的谈话中,他被问到一个问题,我无法完全匹配他对所问问题的回答。然而,问题的症结似乎在于他是在说 SFINAE 独立于重载解析,恰好常用于函数的重载解析。
我理解他的回答的方式是他也在说SFINAE还有另一个用途。
除了重载解析之外,SFINAE 还能应用到哪些地方?在听到他对这个问题的回答之前,我的理解是它唯一的用途是重载解析。
如果您认为合适,您可以根据参数禁用任何模板。
例如,可以想象一个矩阵 class 应该只用算术类型实例化。也就是说,我们希望允许实数和整数矩阵而不是字符串矩阵。你可以这样做:
#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>
会给出一个简单的错误消息,指出没有定义这种类型。这可能会帮助用户提供超过页面的错误消息,即矩阵 class 的某些内部结构没有为 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.