为什么编译enable_if错误(Why compile error with enable_if)

2019-07-17 10:57发布

为什么这不符合gcc48和clang32编译?

#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

Answer 1:

由于您使用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>
{
  ....
};


Answer 2:

好吧,我不知道你想要做什么,但也许这个代码将有所帮助:

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



Answer 3:

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

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


Answer 4:

要获得std::enable_if到这样的工作,你是靠SFINAE。 不幸的是,在该点声明

S<1> s1;

它将所有实例化的S<1>的成员声明。 SFINAE将才开始发挥作用在这一点上,如果S<1>是一个不适形成构建体。 它不是。 不幸的是,它包含一个函数,它是无效的,因而的实例化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); }
};


Answer 5:

对于这种情况,你可以考虑不使用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);
}


文章来源: Why compile error with enable_if