如何用enable_if定义不同的成员函数?

时间:2016-02-25 06:17:02

标签: c++ templates g++ traits

我的代码是:

template<int s>
struct C{
    typename std::enable_if<s == 1, int>::type
    fun(){std::cout<<"fun1";}
    typename std::enable_if<s == 2, int>::type
    fun(){std::cout<<"fun2";}
};

int main() {
    C<1> c;
    c.fun();
}

编译说:

error: functions that differ only in their return type cannot be overloaded

我的编译器是g ++ 4.1.2如果在函数之前使用template<int t = s>,它会警告这是C ++ 11的特性。我想知道如何在不使用C ++ 11的情况下解决这个问题?

3 个答案:

答案 0 :(得分:3)

如果您能够实现enable_if特征,则可以重新排列代码(最小的完整示例)以使其正常工作:

#include<type_traits>
#include<iostream>

struct C {
    template<int s>
    typename std::enable_if<s == 1, int>::type
    fun() { std::cout<<"fun1"; }

    template<int s>
    typename std::enable_if<s == 2, int>::type
    fun() { std::cout<<"fun2"; }
};

int main() {
    C c;
    c.fun<1>();
}

您的版本(几乎与以下版本完全相同)即使使用C ++ 11功能也无法工作,因为它不是名为fun的SFINAE分辨率:

#include<type_traits>
#include<iostream>

template<int s>
struct C {
    typename std::enable_if<s == 1, int>::type
    fun() { std::cout<<"fun1"; }
    typename std::enable_if<s == 2, int>::type
    fun() { std::cout<<"fun2"; }
};

int main() {
    C<1> c;
    c.fun();
}

如果你想让课程像[{1}}那样被实例化,那么简单来说SFINAE就不是这种方式了。
请注意,C<1>在编译时已知您决定使用模板类,因此您可以随时使用它。
它遵循一个可能的解决方案:

s

使用部分特化可以实现另一种解决方案,如下所示:

#include<type_traits>
#include<iostream>

template<int s>
struct C {
    void fun() {
        if(s == 1) {
            std::cout<<"fun1";
        } else if(s == 2) {
            std::cout<<"fun2";
        }
    }
};

int main() {
    C<1> c;
    c.fun();
}

哪一个适合你的主要取决于实际问题,所以我不能说,但至少现在你有几种解决方案可供选择。

答案 1 :(得分:1)

即使我不建议采用这种方法,它也会采用另一种可能的解决方案 我只是为了好奇而将它添加为单独的答案,因为我发现其他答案最合适 无论如何,这个可能是有意义的,因为它显示了如何使用 sfinae 和功能解决方案来解决这样的问题。

#include<iostream>
#include<type_traits>

template<int s>
struct C {
    template<int i>
    typename std::enable_if<i == 1>::type
    fun(){std::cout<<"fun1"<<std::endl;}

    template<int i>
    typename std::enable_if<i == 2>::type
    fun(){std::cout<<"fun2"<<std::endl;}

    void fun() {
        fun<s>();
    }
};

int main() {
    C<1> c1;
    c1.fun();
    C<2> c2;
    c2.fun();
}

答案 2 :(得分:0)

如果您无法按照评论中的说明实施std::enable_if,我会在下面显示替代方案。该解决方案依赖于编译器来优化switch语句,但是仍然可以使用非优化编译器。

#include <iostream>

template <int s>
struct C {
  int fun() {
    switch (s) {
      case 1:
        fun1();
        break;
      case 2:
        fun2();
        break;
      default:
        assert(0);
    }
  }

  inline int fun1() { std::cout << "fun1"; }
  inline int fun2() { std::cout << "fun2"; }
};

修改:我查看了#include <type_traits>的源代码,找到了std::enable_if的模板,如下所示。 GPL许可证适用。来自g++源代码,而不是我自己的工作。我建议将此与skypjacks答案相结合,你最有可能解决你的问题。

// Primary template.
/// Define a member typedef @c type only if a boolean constant is true.
template<bool, typename _Tp = void>
  struct enable_if 
  { };

// Partial specialization for true.
template<typename _Tp>
  struct enable_if<true, _Tp>
  { typedef _Tp type; };