c – 基于可变参数模板的类成员变量

前端之家收集整理的这篇文章主要介绍了c – 基于可变参数模板的类成员变量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
给定一个类型,名称和默认值的列表,我可以轻松编写一个生成有效c代码的工具,该代码声明一个具有每种类型,名称和默认值的成员变量的类.例如,给出列表

> int,foo,42
> float,bar,0.1f

(和类名“Baz”),它会生成

class Baz {
    int foo = 42;
    float bar = 0.1f;
}

如果一个工具可以生成这样一个类,编译器不能为我做这个吗?我正在考虑这些方面的事情(注意:这是伪代码):

template <typename ...MemberTypes> class Baz {
    MemberTypes::type... MemberTypes::name... = MemberTypes::default...;
}

上面的类将被创建类似的东西

using MyBaz = Baz<member_type<int,"foo",42>,member_type<float,"bar",0.1f>>;

可能出现这种情况的原因:

>所有必需的信息都可在编译时获得.外部工具可以轻松完成.
>可以以类似的方式创建具有元组而不是专用成员变量的类(@L_403_0@).
>我可以使用模板特化来对有限的成员组合进行近似.
>模板元编程是turing-complete(C++ templates Turing-complete?),所以“一切”应该是可能的.

这可能是不可能的原因:

>模板参数不能是字符串文字(Passing a string literal as a parameter to a C++ template class),或者实际上不是整数.
>我想不出这样做的方法(弱论点).

如果可以的话,怎么办呢?如果不可能,为什么不呢?即将到来的c 17在这方面有什么改变吗?

更新:示例问题:
通常,配置数据存储为字符串的层次结构或某种其他形式的“任何类型”.然而,这会导致丑陋的代码(config.get< int>(“core.timeout”))并阻止编译器帮助解决例如错别字(config.get< int>(“core.timeuot”)) ).

通过使用其真实类型声明每个配置变量,编译器可以检查类型并防止拼写错误.但是,需要使用自定义代码将配置数据读入正确的成员变量.如果添加了新配置开关,则很容易忘记更新此代码.

只需指定所有成员的类型和名称,然后让编译器自动生成类(包括读取配置文件方法)将会很方便.这是我要求的功能的可能用例.

解决方法

C还没有反射工具.特别是,不可能以您希望的方式生成和操作实体名称.

然而,预处理器可以以有限的方式做到这一点,(在Boost.PP的帮助下,它使得它的标签)可以让我们编写以下内容(直接取自another answer of mine):

#define GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_0(...) \
     ((__VA_ARGS__)) GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_1

#define GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_1(...) \
     ((__VA_ARGS__)) GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_0

#define GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_0_END
#define GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_1_END

// Double the parentheses of a Boost.PP sequence
// I.e. (a,b)(c,d) becomes ((a,b))((c,d))
#define GLK_PP_SEQ_DOUBLE_PARENS(seq) \
    BOOST_PP_CAT(GLK_PP_DETAIL_SEQ_DOUBLE_PARENS_0 seq,_END)


#define MAKE_ONE_VARIABLE(r,data,elem) \
    BOOST_PP_TUPLE_ELEM(0,elem) BOOST_PP_TUPLE_ELEM(1,elem) = BOOST_PP_TUPLE_ELEM(2,elem);

#define MAKE_CLASS(className,members) \
    struct className { \
        BOOST_PP_SEQ_FOR_EACH(MAKE_ONE_VARIABLE,~,GLK_PP_SEQ_DOUBLE_PARENS(members)) \
    }

……并按原样使用它:

MAKE_CLASS(Baz,(int,42)(float,0.1f));

…扩展到:

struct Baz {
    int foo = 42;
    float bar = 0.1f;
};

猜你在找的C&C++相关文章