同じ概念クラスに準拠しているが、ストレージに使用される基礎となるデータ構造が異なる 3 つのクラスがあります。例として、以下に示す 3 つのクラスを取り上げます。
template< typename T >
class A{
std::vector<T> storage;
//etc
};
template<>
class A<bool>{
boost::dynamic_bitset<> storage;
//etc
};
class B{
ComplexUDT storage;
//etc
};
クラス A は、ベクトルを使用するジェネリック クラスです。vector<bool>
クラス A の完全な特殊化の使用を避けるために、 をboost::dynamic_bitset<>
基礎となるストレージとして使用することが提供されています。最後に、クラス B はユーザー定義のデータ型をストレージとして使用します。上記の設計は、コードに多くの冗長性をもたらします。この冗長性を取り除くために、boost::mpl の使用を考えました
template< typename T >
class vec_impl{
std::vector< T > storage;
//impl of methods
};
class bitset_impl{
boost::dynamic_bitset<> storage;
//impl of methods
};
class udt_impl{
ComplexUDT storage;
//impl of methods
};
template<Derived,Storage>
class main_class_gen{
typedef typename boost::mpl::if_<is_complexudt<Storage>,
udt_impl,
typename boost::mpl::if_< is_bool<Storage>,
bitset_impl,
vec_impl<Storage> >::type >::type type
};
class main_class:
public main_class_gen< main_class<Storage>,Storage >::type{
//impl. of methods
};
boost::dynamic_bitset は Container をモデル化しないため、一部のクラス メソッドの実装は vector クラスとは異なります。complexUDT 基底クラスは、他の 2 つのクラスとは大きく異なりますが、いくつかの小さなコード セグメントが共通しています。しかし、現在のリファクタリング アプローチでは、依然としてコードの冗長性が生じます。概念クラスで言及されているすべてのメソッドは、それぞれの実装で実装する必要があります。
だから私の質問は2つあります。
- boost::mpl を使用してビルダー デザイン パターンを実装するにはどうすればよいでしょうか。
- 上記の例で CRTP は何らかの形で役立ちますか?