我有三个类遵循相同的概念类,但在用于存储的底层数据结构上有所不同。作为说明,请参考下面给出的三个类。
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>
,提供了使用boost::dynamic_bitset<>
作为底层存储的A类的完全特化。最后,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基类与其他两个类非常不同,但确实有一些常见的小代码段。但是当前的重构方法仍然会导致代码冗余。概念类中提到的所有方法都必须在每个实现中实现。
所以我的问题是双重的。
答案 0 :(得分:1)
如果我理解你想做什么,这可能适合你:
首先,每个容器必须实现相同的接口。根据需要创建适配器(例如,对于ComplexUDT):
struct AdapterUDT {
typedef double const_reference;
void push_back( double );
private: ComplexUDT complexUDT;
};
虽然通常不推荐使用,但您可以将dynamic_bitset子类化以添加/修改功能。请注意,您不能以多态方式使用它,因为它缺少虚拟析构函数。确保它没有在其他地方使用。
struct AdapterBitset : dynamic_bitset<> { // not recommended
typedef my_biterator iterator;
AdapterBitset( int n ) : dynamic_bitset(n) {}
iterator begin();
};
定义特征以将类型与容器相关联:
template<typename T> struct Trait {
typedef vector<T> type;
};
template<> struct Trait<bool> {
typedef dynamic_bitset<> type;
};
创建一个实现存储接口的模板(减去容器):
template<class T, class Derived> struct Base {
typedef Base<T,Derived> base_t;
typedef typename Trait<T>::type container_type;
typedef typename container_type::const_reference const_reference;
void append( const_reference value ) {
// static polymorphism to access the standardized containers/adapters
static_cast<Derived*>(this)->container.push_back(value);
}
// etc
};
由于您需要基于存储类型的构造函数,因此存储模板必须管理实例化:
template<class T> struct Storage : Base<T,Storage<T>> {
friend struct base_t;
protected: container_type container;
};
// specialize for types with ctor arguments:
template<> struct Storage<bool> : Base<bool,Storage<bool>> {
friend struct base_t;
Storage( int bits ) : container(bits) {}
protected: container_type container;
};
用法示例:
Storage<int> astore; // generic version uses default ctor
astore.append(314);
Storage<bool> bstore(7); // bool specialization requires an int
bstore.append(true);
这应该减少大部分冗余代码。如果这不是你想要的,我需要一个你希望解决的问题的更具体的例子。