C ++ 14元编程:在编译/初始化时自动构建类型列表 [英] C++14 Metaprogramming: Automagically build a list of types at compile / init time

查看:128
本文介绍了C ++ 14元编程:在编译/初始化时自动构建类型列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用C ++ 14以及好奇重复模板模式(CRTP)和 Boost.Hana (或者如果您愿意的话, boost :: mpl ),我可以建立类型列表吗?在编译时(或静态初始化时)没有显式声明?

Using C++14 and some combination of the Curiously Recurring Template Pattern (CRTP) and possibly Boost.Hana (or boost::mpl if you wish), can I build a list of types at compile time (or static initialization time) without an explicit declaration?

例如,我有类似的内容(请参见 Coliru ):

As an example, I have something like this (see it on 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'; } );
}

我要避免显式类型列表- D1 D2 D3 -创建 list ,因为这意味着我必须能够在似乎可以在类声明中或周围告诉编译器将此类添加到您的运行列表中时手动维护该列表。 (我的最终目标是使工厂注册自动化,这是缺少的机制。)

I want to avoid the explicit list of types -- D1, D2, and D3 -- in the creation of list because it means I have to maintain that list manually when it seems like I should be able to tell the compiler in or around the class declaration, "Add this class to your running list". (My ultimate aim is to automate factory registration, and this is the missing mechanism.)

我可以使用一些继承和/或元编程技巧来构成列表吗?编译时间还是静态初始化时间?

Can I do this using some inheritance and/or metaprogramming trickery to compose the list at compile-time or static init time?

推荐答案

在编译时执行此操作将需要状态元编程。在本文此处中,菲利普·罗森(FilipRoséen)解释了如何使用高级C ++ 14:

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>

Matt Calabrese也使用类似的技术在C ++ 11中实现基于语义的概念,请参见视频幻灯片在幻灯片#28。

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.

或者,您可以重新构建代码以支持运行时注册,这要简单得多,并且可以跨MSVC等编译器进行移植。这就是诸如证明 args 使用。它使用通用的 auto_register 类:

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>();

然后您可以编写自己的CRTP类:

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

这篇关于C ++ 14元编程:在编译/初始化时自动构建类型列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆