2012-12-20 102 views
23

为什么这不与gcc48和clang32编译?为什么编译错误与enable_if

#include <type_traits> 

template <int N> 
struct S { 

    template<class T> 
    typename std::enable_if<N==1, int>::type 
    f(T t) {return 1;}; 

    template<class T> 
    typename std::enable_if<N!=1, int>::type 
    f(T t) {return 2;}; 
}; 

int main() { 
    S<1> s1; 
    return s1.f(99); 
} 

GCC错误:

/home/lvv/p/sto/test/t.cc:12:2: error: no type named ‘type’ in ‘struct enable_if<false, int>’ 
    f(T t) {return 2;}; 
^

CLANG错误:

/home/lvv/p/sto/test/t.cc:11:26: error: no type named 'type' in 'std::enable_if<false, int>'; 'enable_if' cannot be used to 
     disable this declaration 
     typename std::enable_if<N!=1, int>::type 
           ^~~~ 
/home/lvv/p/sto/test/t.cc:16:7: note: in instantiation of template class 'S<1>' requested here 
     S<1> s1; 
      ^

编辑 - 解决方案:

我接受的答案,从查尔斯丹参,但实际原因我无法使用建议的解决方法(专门针对N)。我找到了适用于我的其他解决方法。让enable_if取决于T

typename std::enable_if<(sizeof(T),N==1), int>::type 
+1

你确定这是去反正工作?你不能仅仅通过它们的返回类型来重载方法(除非'enable_if'被实现为一种语言结构,而不是像我现在所假设的那样实现一个简单的模板化类)。 – zneak

+0

为什么使enable_if的解决方法完全依赖于T所必需的? –

+0

该解决方案对我无效!我得到了'错误:没有匹配的调用函数...' –

回答

14

由于您使用enable_if无需使用模板参数T在你的函数模板。如果你想专注于结构S有一个特定的模板参数值N,你需要使用类模板专门化。

template <int N, class Enable = void> 
struct S { }; 

template <int N> 
struct S<N, typename std::enable_if<N == 1>::type> 
{ 
    .... 
}; 
5

要获得std::enable_if喜欢这个工作,你是靠SFINAE。不幸的是,点在哪里声明

S<1> s1; 

它将实例所有S<1>的成员声明。如果S<1>是一个不合格的构造,SFINAE只会在这一点上发挥作用。不是这样。不幸的是,它包含一个无效的函数,因此S<>的实例化是无效的。

这样的事情,我可能会推迟到一个单独的模板结构:

template <bool B> 
struct f_functor { 
    template <typename T> 
    static int f(T t) { return 1; } 
}; 

template <> 
struct f_functor<false> { 
    template <typename T> 
    static int f(T t) { return 2; } 
}; 

template <int N> 
struct S { 

    template<class T> 
    typename int f(T t) { return f_functor<N==1>::f(t); } 
}; 
+1

[此问题](http:// stackoverflow。com/questions/6972368/stdenable-if-to-conditionally-compile-a-member-function)有更多的信息。 – Anthony

1

对于这种情况,你可以考虑不使用enable_if在所有。它是更多钞票只需专注F:

template <int N> 
struct S { 
    template<class T> int f(T t); 
}; 

template<int N> 
template<class T> 
int S<N>::f(T t) { return 2; } 

template<> 
template<class T> 
int S<1>::f(T t) { return 1; } 

int main() { 
    S<1> s1; 
    return s1.f(99); 
} 
6

使用默认的布尔模板参数,就像这样:

template <int N> 
struct S { 

    template<class T, bool EnableBool=true> 
    typename std::enable_if<N==1 && EnableBool, int>::type 
    f(T t) {return 1;}; 

    template<class T, bool EnableBool=true> 
    typename std::enable_if<N!=1 && EnableBool, int>::type 
    f(T t) {return 2;}; 
}; 
7

好了,我不知道你想做什么,但也许这个代码将有助于:

#include <iostream> 

template <int N> 
struct S { 

    template<class T=int> 
    typename std::enable_if<N==1, T>::type 
    f(T t) {return 1;} 

    template<class T=int> 
    typename std::enable_if<N!=1, T>::type 
    f(T t) {return 2;} 
}; 

int main() 
{ 
    S<1> s1; 
    S<2> s2; 
    std::cout << s1.f(99) << " " << std::endl << s2.f(5); 
} 

这将打印1和2