SFINAE enable_if 使用 pre c++11 启用构造函数

SFINAE enable_if enable constructor with pre c++11

本文关键字:c++11 启用 构造函数 pre 使用 enable if SFINAE      更新时间:2023-10-16

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

我想通过 SFINAE enable_if语句启用此类的 cpu 变体。

问题是,我需要在没有 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 进行编译。

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

我们可以改用标签,而不是使用 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);
}

不完全是你问的(我想有点愚蠢的解决方案),但是......如果可以接受构造函数接收必需的虚拟参数(未定义类型),则可以在第二个可选参数上激活 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");
}
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_tag初始化data<gpu>,但只有适当的一个会被调用。