编写通用包装器:有条件地将模板参数中的不同类型映射到单个 Class-内部类型

Writing a Generic Wrapper: Conditionally Map different Types from Template Arguments onto a Single Class-Internal Type

TL;DR:如何根据模板参数的类型执行条件类型定义。

我正在为不同的位集实现编写一个包装器。为此,我引用了 std::bitset<>boost::dynamic_bitset<>。我观察到 boost::dynamic_bitset<> 遵循 std::bitset<> 的实现,例如调用代理 class 用于 operator[] 返回的索引处理,其中 class 称为 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); }

所以,在我的 Wrapper 中我可以做 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

我想你不能只是将条件随机放入函数之外的 class space 中,这是我第一次尝试这样做,因为情况很奇怪。

但是如何才能正确处理呢?

您不能使用 if/else 逻辑来定义这样的 typedef。您可以使用助手 class 来推断它。

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 的类型名,您将遇到编译时错误。