C++ 如果与std::is_相同,则启用_拒绝编译

C++ 如果与std::is_相同,则启用_拒绝编译,c++,c++11,C++,C++11,以下代码无法编译 #include <type_traits> #include <fftw3.h> template<class Real> class foo { public: foo(Real* x, size_t length, typename std::enable_if<std::is_same<double, Real>::value>::type* = nullptr) {

以下代码无法编译

#include <type_traits>
#include <fftw3.h>

template<class Real>
class foo
{
public:
    foo(Real* x, size_t length,
        typename std::enable_if<std::is_same<double, Real>::value>::type* = nullptr)
    {
        y = fftw_alloc_real(length);
        fftw_plan plan = fftw_plan_r2r_1d(length, x, y, FFTW_REDFT10, FFTW_ESTIMATE);
        fftw_execute_r2r(plan, x, y);
        fftw_destroy_plan(plan);
    }

    foo(Real* x, size_t length,
        typename std::enable_if<std::is_same<float, Real>::value>::type* = nullptr)
    {
        y = fftwf_alloc_real(length);
        fftwf_plan plan = fftwf_plan_r2r_1d(length, x, y, FFTW_REDFT10, FFTW_ESTIMATE);
        fftwf_execute_r2r(plan, x, y);
        fftwf_destroy_plan(plan); 
    }


private:
    Real* y;
};

int main()
{
    std::vector<double> x{12, 83, 96.3};
    foo<double> fd(x.data(), x.length());

    std::vector<float> xf{12, 82, 96.2};
    foo<float> ff(x.data(), x.length());
}
#包括
#包括
模板
福班
{
公众:
foo(实*x,尺寸和长度,
typename std::enable_if::type*=nullptr)
{
y=fftw_alloc_real(长度);
fftw_平面图=fftw_平面图r2r_1d(长度,x,y,fftw_REDFT10,fftw_估算);
fftw_execute_r2r(计划,x,y);
fftw销毁计划(计划);
}
foo(实*x,尺寸和长度,
typename std::enable_if::type*=nullptr)
{
y=fftwf_alloc_real(长度);
fftwf_平面图=fftwf_平面图r2r_1d(长度,x,y,FFTW_REDFT10,FFTW_估算);
fftwf_执行_r2r(计划,x,y);
fftwf_销毁计划(计划);
}
私人:
真实*y;
};
int main()
{
std::向量x{12,83,96.3};
foo-fd(x.data(),x.length());
std::向量xf{12,82,96.2};
foo-ff(x.data(),x.length());
}
给出错误消息

test.cpp:14:33: error: no type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
    typename std::enable_if<std::is_same<float, Real>::value>::type* = nullptr)
test.cpp:14:33:错误:在“std::\uuu 1::enable_if';”中没有名为“type”的类型enable_if'不能用于禁用此声明
typename std::enable_if::type*=nullptr)

我的语法或对
std::enable\u的理解有什么问题,如果
使其无法编译?有什么办法可以让我使用一个仍然从FFTW调用非模板代码的模板?

让我们从编译器的角度来了解一下。当您说
foo
时,您正在用
Real=double
实例化模板
foo

当我们遇到第一个构造函数时,我们计算
enable\u if
,发现
typename std::enable\u if::type
void
(因为
std::is_same::value==true
)。一切都很好

当我们遇到第二个构造函数时,我们再次尝试通过计算
enable\u if
来实例化它。但是,这次
typename std::enable_if::type
不存在,因为
std::is_same::value==false
。这是一个错误


无论何时尝试实例化
foo
,这两个构造函数中至少有一个是格式错误的。如果您希望SFINAE启动,则需要对构造函数进行模板化:

template<class Real>
class foo
{
public:
    template <typename T>
    foo(T x,
        typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr)
    {
        mantissa_bits = 52;
    }

    template <typename T>
    foo(T x,
        typename std::enable_if<std::is_same<float, T>::value>::type* = nullptr)
    {
        mantissa_bits = 23;
    }


private:
    size_t mantissa_bits;
};
模板
福班
{
公众:
模板
富(tx,,
typename std::enable_if::type*=nullptr)
{
尾数=52位;
}
模板
富(tx,,
typename std::enable_if::type*=nullptr)
{
尾数_位=23;
}
私人:
尾数的大小;
};
虽然我通常看到SFINAE能力的构造函数是这样的:

    template <typename T, typename std::enable_if<std::is_same<double, T>::value, int>::type = 0>
    foo(T x)
    {
        mantissa_bits = 52;
    }
模板
傅(TX)
{
尾数=52位;
}

让我们从编译器的角度来了解它。当您说
foo
时,您正在用
Real=double
实例化模板
foo

当我们遇到第一个构造函数时,我们计算
enable\u if
,发现
typename std::enable\u if::type
void
(因为
std::is_same::value==true
)。一切都很好

当我们遇到第二个构造函数时,我们再次尝试通过计算
enable\u if
来实例化它。但是,这次
typename std::enable_if::type
不存在,因为
std::is_same::value==false
。这是一个错误


无论何时尝试实例化
foo
,这两个构造函数中至少有一个是格式错误的。如果您希望SFINAE启动,则需要对构造函数进行模板化:

template<class Real>
class foo
{
public:
    template <typename T>
    foo(T x,
        typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr)
    {
        mantissa_bits = 52;
    }

    template <typename T>
    foo(T x,
        typename std::enable_if<std::is_same<float, T>::value>::type* = nullptr)
    {
        mantissa_bits = 23;
    }


private:
    size_t mantissa_bits;
};
模板
福班
{
公众:
模板
富(tx,,
typename std::enable_if::type*=nullptr)
{
尾数=52位;
}
模板
富(tx,,
typename std::enable_if::type*=nullptr)
{
尾数_位=23;
}
私人:
尾数的大小;
};
虽然我通常看到SFINAE能力的构造函数是这样的:

    template <typename T, typename std::enable_if<std::is_same<double, T>::value, int>::type = 0>
    foo(T x)
    {
        mantissa_bits = 52;
    }
模板
傅(TX)
{
尾数=52位;
}

SFINAE不是这样做的。谢谢,您能解释一下原因吗?因为替换只适用于模板参数。你的两个任务不是模板。当模板被实例化时,它们都需要格式良好。@user14717是的,但是您真的需要在这里这样做吗?为什么不使用
std::numeric_limits
来获得相同的信息,而不必使用两个不同的构造函数?@user14717那么您应该添加相关的代码-使用SFINAE初始化具有不同值的成员变量是没有意义的,如果您没有提供足够的上下文,我们将很难提供相关的答案。SFINAE不是这样做的。谢谢,您能解释一下原因吗?因为替换只适用于模板参数。你的两个任务不是模板。当模板被实例化时,它们都需要格式良好。@user14717是的,但是您真的需要在这里这样做吗?为什么不使用
std::numeric_limits
来获得相同的信息,而不必使用两个不同的构造函数?@user14717那么您应该添加相关的代码-使用SFINAE初始化具有不同值的成员变量是没有意义的,如果你不提供足够的上下文,我们将很难提供相关的答案。