那么增强模板enable_if呢

时间:2013-06-12 08:23:48

标签: c++ templates c++11

首先我使用enable_if,我在下面编写的代码不会编译,但它在逻辑上似乎是正确的,但是当前的enable_if实现不会支持。

  1 
  2 #include <iostream>
  3 using namespace std;
  4 
  5 template<int N>
  6 struct S{
  7                 template<class T>
  8                 typename enable_if<N==1,T>::type
  9                 f(T t) {return 1;};
 10 
 11                 template<class T>
 12                 T
 13                 f(T t) {return 0;};
 14 };
 15 
 16 int main() {
 17     S<1> s1;
 18     S<2> s2;
 19     cout << s1.f(99) <<" "<< s2.f(99) << endl;
 20     return 0;
 21 }

错误信息准确无误,并且精确指出了问题。

enable_if.cc19:20: error: call of overloaded ‘f(int)’ is ambiguous
enable_if.cc:9:3: error: no type named ‘type’ in   
                         ‘struct std::enable_if<false, int>’

这似乎只是设计不明确的问题,很容易纠正。为了解决这个问题,我可以编写部分专用类模板:

#include <iostream>
using namespace std;

template<int N> struct S{
        template<class T>
        T
        f(T t) {return 0;};
};
template<> struct S<1>{
        template<class T>
        T
        f(T t) {return 1;};
};
int main() {
    S<1> s1;
    S<2> s2;
    cout << s1.f(99) <<" "<< s2.f(99) << endl;
    return 0;
}

但是为了清洁和方便,首先要增强enable_if模板以支持错误代码所敦促的新功能?

  • s1调用f时,可以使用在示例中返回1的更专业的那个。
  • s2调用f时,将使用返回0的一般,即使第一个失败。

4 个答案:

答案 0 :(得分:2)

您可以通过以下方式解决问题:

  1. 在您的功能模板上设置互斥的SFINAE约束;
  2. 强制评估要在通话时执行的enable_if
  3. 例如:

    #include <type_traits>
    
    template<int N>
    struct S
    {
        template <class T>
        typename std::enable_if<N == 1 && std::is_same<T, T>::value, int>::type
        f(T t) {return 1;}
    
        template <class T>
        typename std::enable_if<N != 1, T>::type
        f(T t) {return 0;}
    };
    

    这是live example

答案 1 :(得分:1)

首先,我怀疑你的代码中有拼写错误。启用if应该在T上进行参数化,以编译:{{1​​}}而不是typename enable_if<N==1,T>::type

只需使用第二个重载,如果也是反转条件则启用。它有效:

typename enable_if<N==1,int>::type

答案 2 :(得分:0)

你仍然可以在没有部分专业化的情况下完成,但是:

  1. 您必须确保只存在其中一个功能(否则存在歧义)

  2. 您必须使enable_if条件取决于模板参数。

  3. 这有效:

    #include <iostream>
    #include <type_traits>
    using namespace std;
    
    
    template <int N>
    struct S
    {
        template <typename T>
        typename enable_if<(sizeof(T)>0) && N==1, int>::type
        f(T t) { return 1; }
    
        template <typename T>
        typename enable_if<(sizeof(T)>0) && N!=1, T>::type
        f(T t) { return 0; }
    };
    
    int main()
    {
        S<1> s1;
        S<2> s2;
        cout << s1.f(99) << " " << s2.f(99) << endl;
    }
    

    Live example

答案 3 :(得分:0)

std::enable_if只是选择函数重载的工具。它是作为来自boost的纯库解决方案实现的。我认为选择正确的重载的规则并不容易。但是在涉及enable_if的某些情况下要求更改这一点会使其更复杂。因此,您最好使用部分特化和分离enable_if