c++ - 我们如何使用 boost::mpl 实现 Builder 设计模式?

标签 c++ design-patterns architecture boost-mpl

<分区>

我有三个类,它们遵循相同的概念类,但在用于存储的底层数据结构上有所不同。作为示例,请使用下面给出的三个类。

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 的通用类。避免使用 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 基类与其他两个类有很大不同,但确实有一些共同的小代码段。但是目前的重构方式仍然会导致代码冗余。概念类中提到的所有方法都必须在每个实现中实现。

所以我的问题有两个方面。

  1. 我们如何使用 boost::mpl 实现构建器设计模式?
  2. CRTP 对上述示例有任何帮助吗?

最佳答案

如果我正确理解你想做什么,这可能对你有用:

首先,每个容器都必须实现相同的接口(interface)。根据需要创建适配器(例如对于 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;
};

创建一个实现存储接口(interface)的模板(减去容器):

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);

这应该可以减少大部分冗余代码。如果这不是您要查找的内容,我需要您希望解决的问题的更具体示例。

关于c++ - 我们如何使用 boost::mpl 实现 Builder 设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13025279/

相关文章:

javascript - 这是包装 Javascript 变量的好方法吗?

apache-spark - Kappa 架构 : when insert to batch/analytic serving layer happens

c++ - 私有(private)基类通过子类中的模板友元函数和模板方法影响成员访问

C++ - 获取模板的类型名称,其中该类用作另一个模板

C++ CMake 找不到 Boost 1.63(使用 CLion IDE)

c# - C# 的垃圾收集会导致实时音频应用程序出现问题吗?

asp.net-mvc-3 - 企业中业务实体验证的首选方法

java - MVC 模式中自动调用重复值和一些方法

c# - 没有记录 - 抛出异常的地方

linux - 操作系统如何抢占进程并重新获得控制权?