模板成员函数的接口

时间:2012-07-26 21:40:39

标签: c++ templates interface virtual member-functions

是否有一些常用的方法来定义模板成员函数的接口?我想创建一些纯抽象基类,其中包含应在派生类中重写的模板成员函数的声明。我希望能够通过接口调用派生类的函数。我知道不允许使用虚拟模板成员函数。所以到现在为止我想出了以下解决方案(见下文)。我想知道的是,如果我的方法是糟糕的设计,或者是否有更好的方法来实现我的目标:

编辑:我想要实现的是一个序列化系统(类似于boost :: serialization)。因此,我希望有一个通用的基本接口函数 serialize ,它可以用来保存和加载对象。在调用* do_serialize *函数时,将通过提供的派生归档类确定正确的函数调用save和load。

因为我不确定我提供的解决方案,所以我想问一下是否有更好的方法(甚至更简单的方法)来实现我的目标?

接口:

template<typename Derived>
class Archive{
public:
  virtual ~Archive() = 0 {}

  template<typename T>
  Archive& serialize(T t) {
    Derived* derived = static_cast<Derived*>(this);
    return derived->serialize_derived(t);
  }
};

template<typename Derived>
class Writer : public Archive<Derived> {
public:
  virtual ~Writer() = 0 {}

  template<typename T> 
  void write(const T& t) {
    Derived* derived = static_cast<Derived*>(this);
    derived->write_derived(t);
  }
};

template<typename Derived>
class Reader : public Archive<Derived> {
public:
  virtual ~Reader() = 0 {}

  template<typename T> 
  void read(const T& t) {
    Derived* derived = static_cast<Derived*>(this);
    derived->read_derived(t);
  }
};

派生类:

class BinaryWriter : public Writer<BinaryWriter> {
public:
  template<typename T>
  BinaryWriter& serialize_derived(T t) {
    save(t);
    return *this;
  }

  template<typename T>
  void save(T t) {
    std::cout << "DerivedWriter::save: " << t << std::endl;
  }

  template<typename T> 
  void write_derived(const T& t) {
    std::cout << "DerivedWriter::write_derived: " << t << std::endl;
  }
};

class BinaryReader : public Reader<BinaryReader> {
public:
  template<typename T>
  BinaryReader& serialize_derived(T t) {
    load(t);
    return *this;
  }

  template<typename T>
  void load(T t) {
    std::cout << "DerivedWriter::load: " << t << std::endl;
  }

  template<typename T> 
  void read_derived(const T& t) {
    std::cout << "DerivedReader::read_derived: " << t << std::endl;
  }
};

示例测试函数和调用(注意:类似地需要对Writer / Reader接口的调用(这里省略了其他派生的Writer / Reader-classes(即TextReader,XMLReader等)):( / p >

template<typename Derived, typename T>
void do_serialize(Archive<Derived>& obj, T t) {
  obj.serialize(t);
}

DerivedWriter dw;
DerivedReader dr;

do_serialize(dw, 1);
do_serialize(dr, 2);

输出:

DerivedWriter::save: 1
DerivedReader::read: 2

1 个答案:

答案 0 :(得分:2)

在知道这种技术被称为CRTP之后(感谢pmr)我发现这篇文章CRTP to avoid virtual member function overhead我想回答我的问题。正如Kerrek SB在该帖子中的回答所述,该技术可用于提供接口。在我的情况下,甚至可以为模板成员函数定义此接口。

这种模式似乎很常见(我不确定)所以我会接受它作为我问题的答案。

感谢您的所有回复!