C++14 Metaprogramming: Automagically build a list of types at compile / init time

主宰稳场 提交于 2019-12-05 06:11:51

To do it at compile-time will require "stateful" metaprogramming. In this article here, Filip Roséen explains how to implement the following using extremely advanced 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>

Also, Matt Calabrese used similar techniques to implements semantic-based concepts in C++11, see the video and slides at slide #28.

Of course, these techniques rely on a compiler supporting conformant two-phase name lookup.

Alternatively, you can restucture your code to support runtime registration instead, which is much simpler, and can work portably across compilers such as MSVC. This is what libraries such as Prove or args use. It uses a generic 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>();

Then you can write your own CRTP class:

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>
{};

It sounds like you want to get a compile-time tuple of all types in a namespace or other scope. To do that, you would need static reflection, which has not yet been added to C++ (but would be very useful as you have discovered). You can read one proposal for static reflection here, and the N4428 proposal here.

As a workaround, you could write a macro to simultaneously define the type and implicitly add it to the registry during static initialization.

The only way I know of doing this right now is stateful metaprogramming as described here. But this is tricky, hard to implement and the committee is trying to rule this out as being invalid.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!