那么增强模板enable_if呢?

what about enhance template enable_if

本文关键字:if enable 增强      更新时间:2023-10-16

首先我使用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的通用函数。

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

  1. 在函数模板中设置互斥的sfinae约束;
  2. 强制enable_if在通话时进行评估。
例如:

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

下面是一个的实例

首先,我怀疑您的代码中有一个错字。启用应该在T上参数化的if,编译:typename enable_if<N==1,T>::type而不是typename enable_if<N==1,int>::type

只使用第二个重载,同时启用if,并带反转条件。工作原理:

#include <iostream>
using namespace std;
template<int N>
struct S{
                template<class T>
                typename enable_if<N==1,T>::type
                f(T t) {return 1;};
                template<class T>
                typename enable_if<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;
    return 0;
}

您仍然可以不进行部分专门化,但是:

  1. 你必须确保只有一个函数存在(否则会有歧义)

  2. 必须使enable_if条件依赖于模板参数

如此:

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

生活例子

std::enable_if只是一个选择函数重载的工具。它是作为来自boost的纯库解决方案实现的。我认为选择正确的重载的规则并不容易。但是要求在涉及enable_if的某些情况下改变这一点会使它变得更加复杂。所以你最好使用部分专门化和析取enable_if