编写通用包装器:有条件地将模板参数中的不同类型映射到单个 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
的类型名,您将遇到编译时错误。
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
的类型名,您将遇到编译时错误。