2016-09-27 33 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,最好使用类型扣除代码。它不太容易出错。 –