2017-09-26 14 views
2

複数の型パラメータT1T2を持つテンプレートクラスを作成しようとしています。クラスには、std::promise<T2>のプライベートメンバーがあります。 T2は、限り、あなたはパラメータなしでsetValueを呼び出さないよう、ボイド何でも(あるとき条件付きメンバーの署名とテンプレート型パラメータに基づく実装

template <class T, class T2> 
class Test 
{ 
public: 
    void setValue(T2 value) 
    { 
     promise.set_value(value); 
    } 

    void setValue() 
    { 
     promise.set_value(); 
    } 

private: 
    std::promise<T2> promise; 
}; 

このクラスはうまくコンパイルT2が無効であるとき、私は、コンパイラのエラーを取得:。

error C2182: 'value' : illegal use of type 'void' 

T2は無効ですが、最初のsetValueメソッドを使用したいと思います。T2の1つのパラメータを持ちます。T2が無効の場合は、パラメータを持たない2番目のsetValueメソッドを使用したいと思います。多くの例が、私はテンプレートプログラミングには比較的新しいので、私はそれを動作させるように見えません。

std :: enable_ifでこれを実現できますか?または、テンプレートの特殊化?

答えて

2

ヘルパーテンプレートクラスの特殊化:

#include <future> 

template<typename T> 
class TestHelper 
{ 
public: 
    void setValue(T const& v) 
    { promise.set_value(v); } 

private: 
    std::promise<T> promise; 
}; 

template<> 
class TestHelper<void> 
{ 
public: 
    void setValue() 
    { promise.set_value(); } 

private: 
    std::promise<void> promise; 
}; 

template <class T, class T2> 
class Test : public TestHelper<T2> 
{ 
}; 

int main() 
{ 
    Test<void, int> t; 
    // t.setValue(); // compilation error: no matching function for call to 'std::promise<int>::set_value()' 
    t.setValue(0); 

    Test<void, void> t1; 
    t1.setValue(); 
    // t1.setValue(0); // compilation error: no matching function for call to 'std::promise<void>::set_value(int)' 
} 
+0

私の答えを複製します。 ;) – ypnos

+0

@ypnos:あなたの編集タイムスタンプを確認してください –

+0

ありがとう、それを解決!しかし、 'test'がアクセスできない' promise'にアクセスする別の方法があります。私はその方法をどこに置くべきですか?私はもちろんそれを保護することができますが、私はそれが異なって行うことができますかと思うだけです。 – jkokorian

0

あなたは、基本クラスを条件依存してこの問題を解決することができます

#include <future> 
#include <type_traits> 
#include <iostream> 

template<class T2> 
struct Base { 
protected: 
    std::promise<T2> promise; 
}; 

template<class T2> 
struct BaseWithVariable : public Base<T2> { 
    void setValue(T2 value) 
    { 
     this->promise.set_value(value); 
    } 
}; 

template<typename T2> 
struct BaseWithoutVariable : public Base<T2> { 
    void setValue() 
    { 
     this->promise.set_value(); 
    } 
}; 

template<typename T, typename T2> 
class Test 
: public std::conditional<std::is_same_v<T2, void>, BaseWithoutVariable<T2>, BaseWithVariable<T2>>::type 
{ 
}; 

int main() 
{ 
    Test<int, int> a; 
    a.setValue(5); 
    Test<int, void> b; 
    b.setValue(); 
} 

今、あなたは中間クラスのレベルで専門で同じことを達成できることを実現:

template<class T2> 
struct BaseSetter : public Base<T2> { 
    void setValue(T2 value) 
    { 
     this->promise.set_value(value); 
    } 
}; 

template<> 
struct BaseSetter<void> : public Base<void> { 
    void setValue() 
    { 
     this->promise.set_value(); 
    } 
}; 

template<typename T, typename T2> 
class Test : public BaseSetter<T2> 
{ 
}; 

Baseの使用を省略し、BaseSetterのバリアントのそれぞれに、それぞれ独自のメンバー変数std::promise<T2>またはstd::promise<void>を使用することも、この特定のケースでは傷つけません。

しかし、これらはすべてGCC 7.2.0で実行時にクラッシュします。どうしてか分かりません。

関連する問題