以下代码无法编译
#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());
}
提供错误消息
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)
我的语法或对std::enable_if
的理解是什么导致这不能编译?修复是什么,以便我可以使用仍然从FFTW调用非模板化代码的模板?
答案 0 :(得分:0)
让我们从编译器的角度来看待它。当您说foo<double>
时,您正在使用foo
实例化模板Real = double
。
当我们遇到第一个构造函数时,我们会评估enable_if
,并发现typename std::enable_if<std::is_same<double, Real>::value>::type
为void
(自std::is_same<double, double>::value == true
起)。一切都很好。
当我们遇到第二个构造函数时,我们再次尝试通过评估enable_if
来实例化它。但是,此时typename std::enable_if<std::is_same<float, Real>::value>::type
不存在,因为std::is_same<float, double>::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;
};
虽然我通常看到具有SFINAE功能的构造函数看起来像这样:
template <typename T, typename std::enable_if<std::is_same<double, T>::value, int>::type = 0>
foo(T x)
{
mantissa_bits = 52;
}