为什么我的 SFINAE 开关不工作?
Why is my SFINAE switch not working?
这是我想要实现的 MCVE:
#include <limits>
#include <iostream>
// enable_if (I'm stuck with a c++98 compiler)
template<bool B, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };
// sfinae
template<typename T> const char*
f(typename enable_if<std::numeric_limits<T>::is_integer, T>::type t) { return "sfinae"; }
template<typename T> const char*
f(T t) { return ""; }
// test
int main()
{
std::cout << f(3) << "\n"; // returns an empty string
std::cout << f(3.0) << "\n"; // returns an empty string
}
我期待 f(3)
到 return "sfinae"
的呼叫。我做错了什么?
要调用第一个版本,我必须手动调用f<int>(3)
。我很纳闷。
以下将起作用:
template <typename T>
const char* f_impl(
typename enable_if<std::numeric_limits<T>::is_integer, T>::type t) {
return "sfinae";
}
template <typename T>
const char* f_impl(
typename enable_if<!std::numeric_limits<T>::is_integer, T>::type t) {
return "";
}
template <typename T>
const char* f(T t) {
return f_impl<T>(t);
}
如果您按如下方式调用 f
,您的原始代码将起作用:
std::cout << f<int>(3) << "\n";
std::cout << f<double>(3.0) << "\n";
发生这种情况是因为第一个 f
(SFINAE 的) 永远无法推断出 T
,因为它在 [=19= 中].这意味着它永远不会被调用,除非您明确指定模板参数!
通过添加一个间接层推导 T
然后显式调用 f_impl
,您可以轻松地同时拥有推导和 SFINAE。
在 C++11 中,您甚至不需要 SFINAE:
const char* f_impl(std::true_type) { return "sfinae"; }
const char* f_impl(std::false_type) { return ""; }
template<typename T> const char* f(T t)
{
return f_impl(std::is_integral<T>{});
}
这是我想要实现的 MCVE:
#include <limits>
#include <iostream>
// enable_if (I'm stuck with a c++98 compiler)
template<bool B, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };
// sfinae
template<typename T> const char*
f(typename enable_if<std::numeric_limits<T>::is_integer, T>::type t) { return "sfinae"; }
template<typename T> const char*
f(T t) { return ""; }
// test
int main()
{
std::cout << f(3) << "\n"; // returns an empty string
std::cout << f(3.0) << "\n"; // returns an empty string
}
我期待 f(3)
到 return "sfinae"
的呼叫。我做错了什么?
要调用第一个版本,我必须手动调用f<int>(3)
。我很纳闷。
以下将起作用:
template <typename T>
const char* f_impl(
typename enable_if<std::numeric_limits<T>::is_integer, T>::type t) {
return "sfinae";
}
template <typename T>
const char* f_impl(
typename enable_if<!std::numeric_limits<T>::is_integer, T>::type t) {
return "";
}
template <typename T>
const char* f(T t) {
return f_impl<T>(t);
}
如果您按如下方式调用 f
,您的原始代码将起作用:
std::cout << f<int>(3) << "\n";
std::cout << f<double>(3.0) << "\n";
发生这种情况是因为第一个 f
(SFINAE 的) 永远无法推断出 T
,因为它在 [=19= 中].这意味着它永远不会被调用,除非您明确指定模板参数!
通过添加一个间接层推导 T
然后显式调用 f_impl
,您可以轻松地同时拥有推导和 SFINAE。
在 C++11 中,您甚至不需要 SFINAE:
const char* f_impl(std::true_type) { return "sfinae"; }
const char* f_impl(std::false_type) { return ""; }
template<typename T> const char* f(T t)
{
return f_impl(std::is_integral<T>{});
}