在 C 语言中,SFINAE(替换失败不是错误)可用于根据类型特征有条件地启用或禁用模板专业化。然而,当 SFINAE 在模板返回类型和模板参数中应用不同时,会出现一个常见问题。
考虑以下主要函数:
int main() { foo(5); foo(3.4); }
当SFINAE放入模板参数时,如下图,编译失败错误:
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> auto foo(T) -> void { std::cout << "I'm an integrer!\n"; } template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>::type> auto foo(T) -> void { std::cout << "I'm a floating point number!\n"; }
但是,此实现可以正常工作:
template<typename T> auto foo(T) -> typename std::enable_if<std::is_integral<T>::value>::type { std::cout << "I'm an integrer!\n"; } template<typename T> auto foo(T) -> typename std::enable_if<std::is_floating_point<T>::value>::type { std::cout << "I'm a floating point number!\n"; }
区别在于 C 标准 (14.5.6.1) 中定义函数模板重载的方式。如果重载模板具有相同的函数名称、相同的参数数量和相同的参数类型,则它们是等效的。但是,此比较中不考虑默认模板参数。
在错误的实现中,SFINAE 条件作为默认模板参数包含在内,导致两个相同的函数模板定义了两次。这会触发编译错误。
在正确的实现中,SFINAE 条件用作模板返回类型的一部分。由于这涉及引用模板参数的表达式,因此这两个函数具有不同的签名,从而允许 SFINAE 按预期运行。
以上是C 中的 SFINAE:条件模板专业化的返回类型与参数类型?的详细内容。更多信息请关注PHP中文网其他相关文章!