部分特化模板成员函数

3

我有一个模板类,看起来像下面这样:

template <template <class TypeT> class PoolT=pool_base>
struct pool_map
{
public:
  template <typename U> struct pool { typedef PoolT<U> type };

public:
  template <typename T, size_t S=sizeof(T)>
  T& get( size_t index );

private:
  pool<uint8_t>::type  pool8_;
  pool<uint16_t>::type pool16_;
  pool<uint32_t>::type pool32_;
  pool<uint64_t>::type pool64_;
};

template <template <class TypeT> class PoolT>
template <typename T, size_t S>
inline
T& pool_map<PoolT>::get( size_t index )
{
  // Default case
}

template <template <class TypeT> class PoolT>
template <typename T>
inline
T& pool_map<PoolT>::get<T,8>( size_t index )
{
  // Dispatch to pool8_
}

template <template <class TypeT> class PoolT>
template <typename T>
inline
T& pool_map<PoolT>::get<T,16>( size_t index )
{
  // Dispatch to pool16_
}

template <template <class TypeT> class PoolT>
template <typename T>
inline
T& pool_map<PoolT>::get<T,32>( size_t index )
{
  // Dispatch to pool32_
}

您肯定已经注意到我写的是在一个美好和理想的世界里,有默认模板参数和模板方法的部分特化是可能的(而无需对整个类进行特化)。
我希望听到如何实现同样的效果的建议,即能够为每个大小S拥有专门的方法,以便可以选择适当的池来使用。我尝试在pool_map中添加一个get_pool<size_t>,但几乎发生了相同的问题:我无法特化内部类而不特化外部类...
我所想到的唯一解决方案是使用一个外部get_pool<size_t>类,它将池映射作为参数,并返回对poolX_成员的引用,但我希望避免这样做,因为它似乎不能真正实现静态。
谢谢您的阅读!
2个回答

3

有一个简单的解决方案(也许你没有想到),那就是:

template <typename T>
T& pool_map<PoolT>::get( size_t index )
{
  if (sizeof(T) * CHAR_BIT == 8) {
     // Dispatch to pool8_
  } else if (sizeof(T) * CHAR_BIT == 16) {
     // Dispatch to pool16_
  } else if (...) {
     ...
  } else {
    // Default case
  }
}

但是,如果你把 "dispatch to..." 替换成其他内容,可能会导致编译错误。因此,你可以简单地重载 get() 函数。

template <typename T>
typename std::enable_if<sizeof(T) * CHAR_BIT == 8,T>::type&
    get( size_t index )
{
   ...
}

template <typename T>
typename std::enable_if<sizeof(T) * CHAR_BIT == 16,T>::type&
    get( size_t index )
{
   ...
}

etc.

唯一的问题是默认实现(如果需要)需要一个条件,如sizeof(T) * CHAR_BIT != 8 && sizeof(T) * CHAR_BIT != 16 && sizeof(T) * CHAR_BIT != 32 && sizeof(T) * CHAR_BIT != 64
最后的解决方案(我认为是最好的)仍然是使用一个私有类和一个静态函数,您可以专门化它(您所说的不是“真正的静态方式”)。

我成功解决了它。感谢你非常准确和详尽的回答 :) - NewbiZ

0

一种解决方案是使用enable_ifdisable_if(通常情况下),尽管我还没有测试过。

另一种解决方案是将实现细节简单地转发到一个帮助程序:

namespace helper
{
  template <class T> struct getter { static void Do() {} };

  // specializations by type
}

template <class T>
T& pool_map<T>::get(size_t index) { return helper::getter<T>::Do(); }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接