假设我有一个类似的模板结构

template <typename T> struct Parser {
  //specializations are expected to have these methods
  inline static const byte* objectEnd(const byte* begin, const byte* end);
  inline static const byte* tryRead(const byte* begin, const byte* end, T* obj);
}

它用在不同的类中,其中一些也是模板类(因此它们可能没有关于将哪些类作为参数传递给Parser的完整信息)。
为任何给定类型实现Parser很容易,就像这样:
template<> struct Parser<text_line> {
  inline static const byte* objectEnd(const byte* begin, const byte* end){
    return helper::NextByteOrEnd<'\n'>(begin, end);
  }
  inline static const byte* tryRead(const byte* begin const byte* end, text_line* obj){
    const byte* lf = objectEnd(begin, end);
    obj = text_line(begin, lf);
    return lf==end ? lf : lf+1;
  }
}

我也可以将Parser专门用于一系列模板:
template<int sz> struct Parser<be_uint<sz>> {
  inline static const byte* objectEnd(const byte* begin, const byte* end){
    return begin+be_uint<sz>::size > end ? begin : begin+be_uint<sz>::size;
  }
  inline static const byte* tryRead(const byte* begin const byte* end, be_uint<sz>* obj){
    if(begin + be_uint<sz>::size > end) return begin;
    obj = be_uint<sz>::read(begin);
    return begin + be_uint<sz>::size;
  }
}

但是,如果我想将Parser专用于其他类型的集,该怎么办?假设我有一个类型谓词,例如std::is_base_of<MyHeader, T>,我想写类似
//not actual code - how would I write this?
template<typename Header> struct Parser<Header> {
  static_assert(std::is_base_of<MyHeader, Header>::value, "Wrong!");
  inline static const byte* objectEnd(const byte* begin, const byte* end){
    //MyHeader-specific code here
  }
  inline static const byte* tryRead(const byte* begin const byte* end, Header* obj){
    //MyHeader-specific code here
  }
}

将可选参数添加到Parser的初始定义中,例如
template <typename T, bool MyHeaderFlag = std::is_base_of<MyHeader, T>::value>
struct Parser { //...

似乎不是一个好主意-我(或任何其他程序员)可能想使用其他谓词,例如my_types::is_scientific<T>
这个问题似乎可以用SFINAE解决(如果一个类型适合多个谓词,应该发生什么问题-我更希望它不会导致编译器错误,但这不是很重要,因为这种Parser特化可能放在.cpp文件中)。但是我找不到办法。

需要明确的是,只要客户端代码可以编写类似以下内容的代码,就没有任何限制可以保留“Parser”或其方法(甚至是模板)的确切定义。
Parser<TypeArg>::objectEnd(block.begin, block.begin+block.size)

无需关心TypeArg实际是什么。

最佳答案

如果要对某些类型的集合进行特化处理,最好的方法是在基本模板中添加第二个模板参数。

您可以使用bool进行操作,也可以使用专业类型中的std::enable_if进行实际输入和使用。

我喜欢第二种方式。

template <typename T, typename = void> struct Parser {
  //specializations are expected to have these methods
  inline static const byte* objectEnd(const byte* begin, const byte* end);
  inline static const byte* tryRead(const byte* begin, const byte* end, T* obj);
}

和特化的例子
template<typename Header>
struct Parser<Header, typename std::enable_if<std::is_base_of<MyHeader, Header>::value>::type> {
  inline static const byte* objectEnd(const byte* begin, const byte* end){
    //MyHeader-specific code here
  }
  inline static const byte* tryRead(const byte* begin, const byte* end, Header* obj){
    //MyHeader-specific code here
  }
}

关于c++ - 专门针对不同参数集的模板类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44409569/

10-11 22:34
查看更多