テンプレートメンバー関数のインターフェイスを定義する一般的な方法はありますか?派生クラスでオーバーライドする必要があるテンプレートメンバー関数の宣言を使用して、いくつかの純粋な抽象基本クラスを作成したいと思います。インターフェイスを介して派生クラスの関数を呼び出せるようにしたいよりも。仮想テンプレートメンバー関数が許可されていないことを知っています。だから今まで私は次の解決策を思いついた(下記参照)。私が知りたいのは、私のアプローチが悪いデザインなのか、それとも私の目標を達成するためのより良い方法があるのかということです。
編集:私が実装したいのはシリアル化システムです(boost :: serializationに似ています)。そのため、オブジェクトの保存とロードに使用できる共通のベースインターフェイス関数をシリアル化してもらいたいと思います。保存とロードの正しい関数呼び出しは、* do_serialize *関数を呼び出すときに、提供された派生アーカイブクラスによって決定されます。
提供されたソリューションについてよくわからないので、目標を達成するためのより良い方法(またはさらに簡単な方法)があるかどうかを尋ねたいと思います。
インターフェイス:
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;
}
};
テスト関数と呼び出しの例(注:ライター/リーダーインターフェイスへの呼び出しも同様に必要です(他の派生ライター/リーダークラスはここでは省略されています(つまり、TextReader、XMLReaderなど))):
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