2016-09-27 30 views
1

TL; DR:如何根據模板參數的類型執行條件類型定義。寫一個通用包裝器:有條件地將不同類型從模板參數映射到單一類內部類型

我正在爲不同的bitset實現編寫一個Wrapper。爲此我引用std::bitset<>boost::dynamic_bitset<>。我注意到boost::dynamic_bitset<>跟在std::bitset<>的執行之後,例如通過調用代理類來處理由operator[]返回的索引處理,該類名爲reference,正如std::bitset<>一樣。即模板與位集類型BITSET - - 所以,這是因爲在我的包裝是有用的話,我可以做

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

,它將兩個,std::bitset<>boost::dynamic_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或類似的東西,但這可能不適用於另一個不使用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()); 

上述方法不起作用,即使它看起來很笨重。

這是除了我的問題的問題,但只是爲了完整性,這是錯誤:

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; 
}; 

然後用:

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

對於沒有TypedefSelector typenames,你會得到編譯時錯誤。

+0

謝謝。我想到我也可以將'INDEX_TYPE'作爲模板參數,所以對於'BITSET'只有3個(或k個k)類型沒有限制,但是接口會更麻煩一點,因爲附加的模板參數。什麼是更好的風格呢? –

+0

@lotolmencre,最好使用類型扣除代碼。它不太容易出錯。 –