我可以使用类型列表构建抽象访问者吗?
Can I build an abstract visitor using a typelist?
所以我有一个抽象 class 它是任何使用对象集合的访问者的基础:
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
>;
每当我添加新类型时都必须更新访问者 class 似乎很遗憾...有什么方法可以通过传递 class 自动生成访问者 class =13=]?
std::enable_if
和 boost::mpl::find
似乎是可行的方法,但我不能模板化虚拟方法吗?
你不能可变参数模板虚方法,但你可以模板基 classes:
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...>> {};
但是,我更喜欢单级多重继承,因为它产生更清晰的类型层次结构,更容易在调试器中检查。
在这两种情况中的任何一种情况下,都会有一些 space 开销,因为 visitor
将包含 n
指向其 vtable 的 vtable 指针,以允许转换为基本类型。 space 开销较少但编译时间开销很大的替代方法是使用 Boost.Preprocessor 通过 BOOST_PP_REPEAT
:[=17= 生成 n
-length class 主体]
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>;
所以我有一个抽象 class 它是任何使用对象集合的访问者的基础:
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
>;
每当我添加新类型时都必须更新访问者 class 似乎很遗憾...有什么方法可以通过传递 class 自动生成访问者 class =13=]?
std::enable_if
和 boost::mpl::find
似乎是可行的方法,但我不能模板化虚拟方法吗?
你不能可变参数模板虚方法,但你可以模板基 classes:
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...>> {};
但是,我更喜欢单级多重继承,因为它产生更清晰的类型层次结构,更容易在调试器中检查。
在这两种情况中的任何一种情况下,都会有一些 space 开销,因为 visitor
将包含 n
指向其 vtable 的 vtable 指针,以允许转换为基本类型。 space 开销较少但编译时间开销很大的替代方法是使用 Boost.Preprocessor 通过 BOOST_PP_REPEAT
:[=17= 生成 n
-length class 主体]
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>;