2017-09-19 13 views
1
次のコードは、エラーメッセージに与える

のstd :: enable_ifは

#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()); 
} 

のコンパイルに失敗し

をコンパイルすることを拒否します私の構文やstd::enable_ifの理解が間違っている何

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) 

これはコンパイルされませんか? FFTWのテンプレート化されていないコードを依然として呼び出すテンプレートを使用できるように、修正は何ですか?

+0

をこれは、あなたがSFINAEを行う方法ではありません。 – StoryTeller

+0

ありがとう、なぜ説明できますか? – user14717

+0

置換はテンプレートパラメータにのみ適用されるためです。あなたの2つのc'torsはテンプレートではありません。テンプレートは、インスタンス化されたときに両方とも整形式である必要があります。 – StoryTeller

答えて

0

コンパイラの観点から見ていきましょう。 foo<double>と言うとき、テンプレートfooReal = doubleでインスタンス化しています。

我々は最初のコンストラクタに遭遇したとき、私たちはenable_ifを評価し、typename std::enable_if<std::is_same<double, Real>::value>::typevoid(​​以降)であることがわかります。すべてが順調。

2番目のコンストラクタが発生したら、enable_ifを評価してもう一度インスタンス化しようとします。ただし、std::is_same<float, double>::value == false以降はtypename std::enable_if<std::is_same<float, Real>::value>::typeは存在しません。これはエラーです。


あなたがfooをインスタンス化しようとするときはいつでも、これら2つのコンストラクタのうちの少なくとも1つが病気に形成されます。私は通常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; 
    } 
関連する問題