c++ - 我可以使用类型列表构建抽象访问者吗?

标签 c++ boost

所以我有一个抽象类,它是任何使用对象集合的访问者的基础:

class visitor
{
  virtual void visit(foo) = 0;
  virtual void visit(bar) = 0;
  virtual void visit(baz) = 0;
  virtual void visit(quux) = 0;
};

但我也将所有这些类型保存在 boost::mpl::list 中:

using type_list = boost::mpl::list<
  foo,
  bar,
  baz,
  quux
>;

每当我添加新类型时都必须更新访问者类,这似乎是一种耻辱...有什么方法可以通过传递 type_list 自动生成访问者类吗?

std::enable_ifboost::mpl::find 似乎是可行的方法,但我不能模板虚拟方法,可以吗? p>

最佳答案

您不能使用可变参数模板虚拟方法,但可以模板化基类:

template<class T> class singleVisitorBase { virtual void visit(T) = 0; };

template<class list> class visitor;
template<class... Ts> class visitor<boost::mpl::list<Ts...>>
    : singleVisitorBase<Ts>... {};

另一种方法是使用递归继承:

template<class list> class visitor;
template<> class visitor<boost::mpl::list<>> {};
template<class T, class... Ts> class visitor<boost::mpl::list<T, Ts...>>
    : singleVisitorBase<T>, visitor<boost::mpl::list<Ts...>> {};

但是,我更喜欢单级多重继承,因为它会产生更清晰的类型层次结构,更容易在调试器中检查。

在这两种情况下,都会有一些空间开销,因为 visitor 将在其 vtable 中包含 n 个 vtable 指针,以允许强制转换为基类型。另一种空间开销较小但编译时间开销较大的替代方案是使用 Boost.Preprocessor 通过 BOOST_PP_REPEAT 生成 n 长度的类主体:

template<class list, std::size_t N> class visitorImpl;
#define VISITOR_MAX 32
#define VISITOR_VISIT(z,I,_) \
    virtual void visit(typename boost::mpl::at<list, I>::type) = 0;
#define VISITOR_CLASS(z,N,_) \
template<class list>         \
class visitorImpl<list, N>   \
{                            \
    BOOST_PP_REPEAT(N, VISITOR_VISIT, ) \
};
BOOST_PP_REPEAT(VISITOR_MAX, VISITOR_CLASS, )
template<class list> using visitor
    = visitorImpl<list, typename boost::mpl::size<list>::type::value>;

关于c++ - 我可以使用类型列表构建抽象访问者吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27941774/

相关文章:

c++ - 我如何在 C++ 中创建一个类,在初始化时,在调用其名称时返回一个 bool 值,但没有显式函数调用 make,如 ifstream

c++ - 窗口不显示图像 SDL

c++ - cURL c++ 和 gunzip

c++0x 编译但 eclipse 编辑器错误,即使使用 -gnu++0x 发现

c++ - boost 共享内存。当前有多少进程正在使用共享内存?

c++ - 安装旧的 2005 BOOST 库时遇到问题

c++ - 将同一类的方法实现放在不同的目标文件中

c++ - 在 C++ 中解决 Project Euler 问题的最佳 bignum 库?

c++ - 如何改变高斯分布的种子( boost )

c++ - 使用 composing() 和 implicit_value() boost program_options 不是 "composed"