SFINAE enable_if使用pre c ++ 11

时间:2017-06-02 17:38:12

标签: c++ templates sfinae clang++

我有两个不同版本的构造函数(一个用于gpu,一个用于cpu),但两个版本的其余版本几乎相同。

我想通过SFINAE enable_if语句启用此类的cpu-variant。

问题是,我需要在没有C ++ 11和clang ++的情况下编译它。

以下代码正常运行,但它会产生五个警告:

warning: default template arguments for a function template are a C++11
      extension [-Wc++11-extensions]

有没有办法,使用sfinae而不需要用标准C ++ 11编译c ++代码而没有c ++ 11警告?

以下是代码:

#include <iostream>

enum arch_t{cpu, gpu};

template<bool B, class T=void>
struct enable_if {};

template<class T>
struct enable_if<true, T> { typedef T type; };

template<typename T1, arch_t arch>
class data {
    public:

    template<arch_t a=arch, typename enable = typename enable_if<a==cpu, void>::type, typename tmp = enable>
    data(void)
    {
        std::cout << "-CPU()" << std::endl;
    }

    template<arch_t a=arch, typename = typename enable_if<a!=cpu, void>::type>
    data(void)
    {
        std::cout << "-GPU()" << std::endl;
    }
};

int main()
{
    data<int,gpu> gpu_data;
    data<int,cpu> cpu_data;
}

预期(也是实际)输出: -GPU() -CPU()

我使用clang ++ - 3.8进行编译。

3 个答案:

答案 0 :(得分:1)

建议将其作为替代解决方案。

我们可以使用标签代替SFINAE。这里,标签是一个空结构,其名称作为一条信息(标签)。然后我们可以使用标记重载函数(包括构造函数),因为它是一个类型。所以在这种情况下我们可以有类似

的东西
struct cpu_arch_t {} cpu_arch;
struct gpu_arch_t {} gpu_arch;

template<typename T1>
class data {
public: 
    data(cpu_arch_t)
    {
        std::cout << "-CPU()" << std::endl;
    }

    data(gpu_arch_t)
    {
        std::cout << "-GPU()" << std::endl;
    }
};

然后我们可以像

一样使用它
int main()
{
    data<int> gpu_data(gpu_arch);
    data<int> cpu_data(cpu_arch);
}

答案 1 :(得分:1)

不完全是你提出的问题(我想是一个有点愚蠢的解决方案)但是......如果你能接受你的构造函数接收一个必需的伪参数(未定义类型),你可以在第二个可选参数上激活SFINAE。

以下是一个工作示例

#include <iostream>

enum arch_t{cpu, gpu};

template <bool B, typename T = void>
struct enable_if
 { };

template <typename T>
struct enable_if<true, T>
 { typedef T type; };

template <typename T1, arch_t arch>
class data
 {
   public:
      template <typename T>
      data (T const &, typename enable_if<arch==cpu, T>::type * = 0)
       { std::cout << "-CPU()" << std::endl; }

      template <typename T>
      data (T const &, typename enable_if<arch!=cpu, T>::type * = 0)
       { std::cout << "-GPU()" << std::endl; }
 };

int main ()
 {
   data<int,gpu> gpu_data(0);
   data<int,cpu> cpu_data("abc");
 }

答案 2 :(得分:0)

id, title

您必须使用enum arch_t{cpu, gpu}; template<arch_t, arch_t> struct arch_tag { }; template<arch_t arch> class data { private: public: data(arch_tag<cpu, arch>) { std::cout << "-CPU()" << std::endl; } data(arch_tag<gpu, arch>) { std::cout << "-GPU()" << std::endl; } }; struct data_tag:arch_tag<cpu, cpu>, arch_tag<gpu, gpu> {}; int main(){ data<cpu> c = data_tag(); (void)c; data<gpu> g = data_tag(); (void)g; } 初始化data<gpu>,但只会调用相应的一个。