加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 03:41:24 所属栏目:百科 来源:网络整理
导读:给定一个类型,名称和默认值的列表,我可以轻松编写一个生成有效c代码的工具,该代码声明一个具有每种类型,名称和默认值的成员变量的类.例如,给出列表 int,foo,42 float,bar,0.1f (和类名“Baz”),它会生成 class Baz { int foo = 42; float bar = 0.1f;} 如果
给定一个类型,名称和默认值的列表,我可以轻松编写一个生成有效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>>;

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

>所有必需的信息都可在编译时获得.外部工具可以轻松完成.
>可以以类似的方式创建具有元组而不是专用成员变量的类(Declare member variables from variadic template parameter).
>我可以使用模板特化来对有限的成员组合进行近似.
>模板元编程是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;
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读