met*_*tal 6 c++ crtp template-meta-programming c++14 boost-hana
使用C++ 14和奇怪的重复模板模式(CRTP)和可能的Boost.Hana(或者boost::mpl如果你愿意)的某种组合,我可以在编译时(或静态初始化时间)构建一个类型列表而不需要显式声明吗?
举个例子,我有类似的东西(见上Coliru):
#include <iostream>
#include <boost/hana/tuple.hpp>
#include <boost/hana/for_each.hpp>
namespace
{
struct D1 { static constexpr auto val = 10; };
struct D2 { static constexpr auto val = 20; };
struct D3 { static constexpr auto val = 30; };
}
int main()
{
// How to avoid explicitly defining this?
const auto list = boost::hana::tuple< D1, D2, D3 >{};
// Do something with list
boost::hana::for_each( list, []( auto t ) { std::cout << t.val << '\n'; } );
}
Run Code Online (Sandbox Code Playgroud)
我想避免显式的类型列表 - D1,D2和D3- 在创建中list因为这意味着我必须手动维护该列表,因为我似乎应该能够在类声明中或周围告诉编译器,"将此类添加到运行列表中".(我的最终目标是自动化工厂注册,这是缺失的机制.)
我可以使用一些继承和/或元编程技巧在编译时或静态初始化时组成列表吗?
要在编译时完成此操作,需要“有状态”元编程。在这篇文章中, Filip Ros\xc3\xa9en 解释了如何使用极其先进的 C++14 实现以下内容:
\n\nLX::push<void, void, void, void> ();\nLX::set<0, class Hello> ();\nLX::set<2, class World> ();\nLX::pop ();\n\nLX::value<> x; // type_list<class Hello, void, class World>\nRun Code Online (Sandbox Code Playgroud)\n\n此外,Matt Calabrese 使用类似的技术在 C++11 中实现基于语义的概念,请参阅幻灯片 #28 中的视频和幻灯片。
\n\n当然,这些技术依赖于支持一致的两阶段名称查找的编译器。
\n\n或者,您可以重新构建代码以支持运行时注册,这要简单得多,并且可以跨编译器(例如 MSVC)移植。这就是Prove或args等库所使用的。它使用一个泛型auto_register类:
template<class T, class F>\nint auto_register_factory()\n{\n F::template apply<T>();\n return 0;\n}\n\ntemplate<class T, class F>\nstruct auto_register\n{\n static int static_register_;\n // This typedef ensures that the static member will be instantiated if\n // the class itself is instantiated\n typedef std::integral_constant<decltype(&static_register_), &static_register_> static_register_type_;\n};\n\ntemplate<class T, class F>\nint auto_register<T, F>::static_register_ = auto_register_factory<T, F>();\nRun Code Online (Sandbox Code Playgroud)\n\n然后你可以编写自己的CRTP类:
\n\nstruct foo_register\n{\n template<class T>\n static void apply()\n {\n // Do code when it encounters `T`\n }\n};\n\ntemplate<class Derived>\nstruct fooable : auto_register<Derived, foo_register>\n{};\nRun Code Online (Sandbox Code Playgroud)\n