要在编译时完成此操作,需要“有状态”元编程。在本文中here http://b.atch.se/posts/constexpr-meta-container/Filip Roséen 解释了如何使用极其先进的 C++14 实现以下内容:
LX::push<void, void, void, void> ();
LX::set<0, class Hello> ();
LX::set<2, class World> ();
LX::pop ();
LX::value<> x; // type_list<class Hello, void, class World>
此外,Matt Calabrese 使用类似的技术在 C++11 中实现基于语义的概念,请参阅 and slides https://github.com/boostcon/2011_presentations/blob/master/thu/Boost.Generic.pdf幻灯片#28。
当然,这些技术依赖于支持一致的两阶段名称查找的编译器。
或者,您可以重新构建代码以支持运行时注册,这要简单得多,并且可以跨编译器(例如 MSVC)移植。这就是诸如Prove https://github.com/pfultz2/Prove or args https://github.com/pfultz2/args使用。它使用一个通用的auto_register
class:
template<class T, class F>
int auto_register_factory()
{
F::template apply<T>();
return 0;
}
template<class T, class F>
struct auto_register
{
static int static_register_;
// This typedef ensures that the static member will be instantiated if
// the class itself is instantiated
typedef std::integral_constant<decltype(&static_register_), &static_register_> static_register_type_;
};
template<class T, class F>
int auto_register<T, F>::static_register_ = auto_register_factory<T, F>();
然后你可以编写自己的CRTP类:
struct foo_register
{
template<class T>
static void apply()
{
// Do code when it encounters `T`
}
};
template<class Derived>
struct fooable : auto_register<Derived, foo_register>
{};