2016-09-27 4 views
1

TL; DR:テンプレート引数の型に応じて条件付きtypedefを実行するにはどうすればよいですか。ジェネリックラッパーの作成:テンプレート引数からさまざまな型を条件付きで単一のクラス内部型に条件付きでマップする

私は異なるビットセットの実装のためのWrapperを書いています。そのために私はstd::bitset<>boost::dynamic_bitset<>を参照しています。私はboost::dynamic_bitset<>std::bitset<>の実装に従うことを観察します。たとえば、によって返されるインデックス処理用のプロキシクラスを呼び出すことによって、referenceというクラスがあります。ちょうどstd::bitset<>と同じです。私はその後、

typename BITSET::reference operator[](INDEX_TYPE i) 
    { return bitset[i]; } 

を行うことができますし、それは、std::bitset<>boost::dynamic_bitset<>の両方のために動作します - それはビットセットタイプBITSETでテンプレート化された - 私のラッパーであるためので、それは便利です。

しかし、そのように並列化されていない機能があります。例えばのように、インデックス・タイプとしてboost::dynamic_bitset<>typedef std::size_t size_type;を宣言します。

bool operator[](size_type pos) const { return test(pos); }

しかしstd::bitset<>は、単にそのためsize_t使用しています:

_GLIBCXX_CONSTEXPR bool                   
operator[](size_t __position) const 
{ return _Unchecked_test(__position); } 

だから、私のラッパーで、私はそのようなtypedef size_t INDEX_TYPEか何かを行うことができますこれらの2つが偶然(またはそうでない)行うので、size_tを使用しない別の実装では動作しない可能性があります。

明らかにこれを行うための汎用的な方法は本当にありませんがあるが、私は、少なくとも何らかの形で条件付きでこれに似て、私のINDEX_TYPEを定義することができます。

template <class BITSET, class T> 
/** 
* 
* @tparam T Use this parameter to pass on the template parameter that 
*   was used to template BITSET 
*/ 
class BitsetWrapper 
{ 
public: // typedefs 
    if (typeid(BITSET) == bool::dynamic_bitset<T>) 
     typedef tyeanme BITSET::size_type INDEX_TYPE; 
    else if (typeid(BITSET) == std::bitset<T>) 
     typedef size_t INDEX_TYPE; 
    else if (typeid(BITSET) == BitSet<T>) // my own implementation 
     typedef BITSET::INDEX_TYPE INDEX_TYPE; 
    else 
     throw std::invalid_argument("unsupported type: "+typeid(BITSET).name()); 

上記の方法がうまくいかないと、それは非常にルックスをした場合でも、 clunky。

それは私の質問のポイント以外にもあるが、ちょうど完全性のため、これは誤りです:私はあなただけの関数の外側のクラスの空間にランダムに条件文を置くことができないと思います

bitsetWrapper.hpp:34:5: error: expected member name or ';' after declaration specifiers 
    if (typeid(BITSET) == bool::dynamic_bitset<T>) 
    ^
bitsetWrapper.hpp:36:5: error: expected member name or ';' after declaration specifiers 
    else if (typeid(BITSET) == std::bitset<T>) 
    ^
bitsetWrapper.hpp:38:5: error: expected member name or ';' after declaration specifiers 
    else if (typeid(BITSET) == BitSet<T>) 
    ^
bitsetWrapper.hpp:40:5: error: expected member name or ';' after declaration specifiers 
    else 

、これはでした私が奇妙な状況のためにこれを試したのは初めてです。

これはどのように正しくアプローチできますか?

答えて

2

if/else論理を使用してtypedefを定義することはできません。ヘルパークラスを使用して推論することができます。

その後、
template <typename T> struct TypedefSelector; 

template <typename T> struct TypedefSelector<boost::dynamic_bitset<T>> 
{ 
    using IndexType = BITSET::size_type; 
}; 

template <typename T> struct TypedefSelector<std::bitset<T>> 
{ 
    using IndexType = size_t; 
}; 

template <typename T> struct TypedefSelector<BitSet<T>> 
{ 
    using IndexType = BITSET::INDEX_TYPE; 
}; 

と使用:TypedefSelectorを持っていない型名については

template <class BITSET, class T> 
class BitsetWrapper 
{ 
    using INDEX_TYPE = typename TypedefSelector<T>::IndexType; 
    ... 
}; 

、あなたは時間のコンパイルエラーを取得します。

+0

ありがとうございました。私は 'INDEX_TYPE'にテンプレートパラメータを作ることができたので、' BITSET'には3つ(またはいくつかのkではk)のタイプに制限はありませんでしたが、インターフェイスはもう少し面倒ですこれは、追加のテンプレートパラメータのためです。しかし、より良いスタイルは何ですか? –

+0

@lotolmencre、タイプ控除コードを使用する方が良いです。エラーの発生が少ない –

関連する問題