2017-03-08 55 views
0

这里是我想要达到的MCVE:为什么我的SFINAE开关不工作?

#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 
} 

try it on coliru

我期待调用f(3)返回"sfinae"。我究竟做错了什么?

对于第一个要调用的版本,我必须手动调用f<int>(3)。我很困惑。

回答

4

下面的工作:

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); 
} 

on coliru


,如果你调用f如下您的原始代码将工作:

std::cout << f<int>(3) << "\n"; 
std::cout << f<double>(3.0) << "\n"; 

这是因为第一f(SFINAE o ne)将永远无法推断出T,因为它位于non-deduced context之内。这意味着它将永远不会被调用,除非你明确指定模板参数!

通过添加一个间接层,推导出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>{}); 
} 
+0

事实上(感谢),但为什么呢? – YSC

+0

编辑说明... –

+0

@YSC:完成,有帮助吗? –