Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有可变成员数的结构或类_C++_Templates_Metaprogramming - Fatal编程技术网

C++ 具有可变成员数的结构或类

C++ 具有可变成员数的结构或类,c++,templates,metaprogramming,C++,Templates,Metaprogramming,我想创建一个结构/类,该结构/类具有可变数量的类成员,这些成员可以在编译阶段决定(就像在模板元编程中所做的那样) 示例:假设类型和变量名都要指定,比如类型T1变量名应该是varName1等等…… template <class T1 (varName1) > MyClass { T1 varName1; } template <class T1 (varName1), class T2 (varName2) > MyClass { T1 varNa

我想创建一个结构/类,该结构/类具有可变数量的类成员,这些成员可以在编译阶段决定(就像在模板元编程中所做的那样)

示例:假设类型和变量名都要指定,比如类型T1变量名应该是varName1等等……

template <class T1 (varName1) >
MyClass
{
     T1 varName1;

}

template <class T1 (varName1), class T2 (varName2) >
MyClass
{
     T1 varName1;
     T1 varName2;
}
模板
类名
{
T1 varName1;
}
模板
类名
{
T1 varName1;
T1 varName2;
}
在主代码中,可以像下面这样声明,或者以其他方式指定类型和名称

MyClass Obj

MyClass::somefunc()可以访问变量名 如下

MyClass::somefunc()
{
     std::cout <<" abc value : " << abc << std::endl;
     std::cout <<" xyz value : " << xyz << std::endl;
}
MyClass::somefunc()
{

std::cout模板不能指定变量名。如果您在编译时决定类中包含什么,您应该能够直接在源代码中指定它


你可以用一些宏来完成你想要的,但我不敢冒险进入这个黑暗的领域。

你不能用模板指定名称,只能用类型或某些类型的值。你可以用宏来完成,但是在语言中尝试做太多的事是一个陷阱,我已经陷入了太多的陷阱她的路径可能对你有用:代码生成

考虑编写一个脚本,读入一些配置文件并写出类的定义。将脚本添加到构建过程中。这可能比模板元编程或宏skulduggery的黑魔法更容易维护和理解

python是我在脚本中使用的东西,每个类的配置都是一些易于解析的东西,比如json,但这些都是次要问题


在我当前的项目中,我们有数千行生成的文件,分布在100多个文件中……这些生成脚本被相对定期地修改,而且没有任何痛苦。

我记得安德烈·亚历山德雷斯库(Andrei Alexandrescu)在他的书《现代C++》中描述了类似的内容.我这里没有副本,所以我不能确切地说出它是什么,在哪里

正如其他人所指出的,不可能将名称作为模板参数,但他创建了一个可以访问的结构,如
data.get()
或类似的东西。如果有一种类型的多个数据,您可以执行
data.get()


也许这会有帮助。

您可以做类似的事情,但它们不会有不同的名称:

template <class T, int num_t >
MyClass
{
     T var[num_T];
};
模板
类名
{
T var[num_T];
};

这忽略了边界检查,但这是另一回事。

不可能如前所述。您可以使用boost的预处理器库获得等效的功能

最终,你所要求的不同于简单地说

struct Members
{
    int a_;
    double b_;
};
…变成

template <class Members>
class Add_Stuff : public Members
{
  public:
    doSomething() { ... };
};

……可以生成一些C++代码ala.…/p>

std::ostringstream streaming;
streaming << "    void somefunc() const\n{\n    std::cout ";

cout << "class " << class_name << "\n{\n";
while (cin.getline(type) && cin.getline(identifier))
{
    cout << "    " << type << ' ' << identifier << '\n';
    streaming << "<< \"" << identifier << " \" << identifier << "\n        ";
}
cout << "  public:\n" << streaming.str() << "\n"
        "};\n";
std::ostringstream流媒体;
流Loki的类型列表。
对我来说很复杂。但是我想你想要的东西可以用这个来完成。

看看


这允许任意数量的数据元素(但在编译时是固定的),并允许对每个索引进行类型安全访问。

我发现这个问题没有明确说明,不清楚目的是什么

序列化,我会考虑。

对于命名的、严格类型的可选参数,一种可能是使用,另一种更简单的可能是使用。它本质上是一组宏,通过一些不可穿透的内部模板黑魔法,生成像您所要求的类。我在Dobbs博士期刊上写了一篇关于它的文章,但下面是一个说明mai的使用示例n优点是,生成的选项类可以与另一个类层次结构并行扩展:

#include <iostream>
#include <progrock/cppx/arguments/options_boosted.h>

struct AbstractButton
{
    // These members are not part of the cppx options scheme: in actual
    // usage you will instead have e.g. some API level widget states.
    int     hTextAlign;
    int     vTextAlign;
    int     buttonPlacement;

    // Defines a local class 'Options' with specified options & defaults.
    CPPX_DEFINE_OPTIONCLASS( Options, CPPX_OPTIONS_NO_BASE,
        ( hTextAlign,       int,        0   )
        ( vTextAlign,       int,        0   )
        ( buttonPlacement,  int,        0   )
        )

    explicit AbstractButton( Options const& params = Options() )
        : hTextAlign( params.hTextAlign() )
        , vTextAlign( params.vTextAlign() )
        , buttonPlacement( params.buttonPlacement() )
    {}
};

struct CheckBox: AbstractButton
{
    bool    isAuto;
    bool    is3State;

    // Defines an extension of the base class' 'Options' class.
    CPPX_DEFINE_OPTIONCLASS( Options, AbstractButton::Options,
        ( isAuto ,          bool,       true    )
        ( is3State,         bool,       false   )
        )

    explicit CheckBox( Options const& params = Options() )
        : AbstractButton( params )
        , isAuto( params.isAuto() )
        , is3State( params.is3State() )
    {}
};

void show( CheckBox const& cb )
{
    std::cout
        << std::boolalpha
        << "hTextAlign = " << cb.hTextAlign
        << ", isAuto = " << cb.isAuto << ".\n";
}

int main()
{
    typedef CheckBox::Options   CBOptions;

    CheckBox        widget1;
    show( widget1 );                // 0, true (the default values)

    CheckBox        widget2( CBOptions().hTextAlign( 1 ) );
    show( widget2 );                // 1, true

    CheckBox        widget3( CBOptions().hTextAlign( 1 ).isAuto( false ) );
    show( widget3 );                // 1, false
}
#包括
#包括
结构抽象按钮
{
//这些成员不是cppx期权计划的一部分:实际上
//相反,您将拥有一些API级别的小部件状态。
int-hTextAlign;
int-vTextAlign;
int按钮位置;
//使用指定的选项和默认值定义本地类“Options”。
CPPX_定义_选项类(选项、CPPX_选项、无基础、,
(hTextAlign,int,0)
(vTextAlign,int,0)
(按钮位置,int,0)
)
显式抽象按钮(Options const¶ms=Options())
:hTextAlign(params.hTextAlign())
,vTextAlign(params.vTextAlign())
,buttonPlacement(参数buttonPlacement())
{}
};
结构复选框:AbstractButton
{
布尔·伊萨托;
布尔值为3状态;
//定义基类“选项”类的扩展。
CPPX_定义_选项类(选项,抽象按钮::选项,
(伊萨托,布尔,真)
(is3State、bool、false)
)
显式复选框(Options const¶ms=Options())
:AbstractButton(参数)
,isAuto(params.isAuto())
,is3State(params.is3State())
{}
};
无效显示(复选框const&cb)
{
标准::cout

通过模板元编程和少量预处理,可以实现接近理想的语法:

//one has to "declare" once an attribute name to be able to use
//it later in any number of class declarations
DECLARE_ATTRIBUTE_NAME(foo);
DECLARE_ATTRIBUTE_NAME(quux);
DECLARE_ATTRIBUTE_NAME(bar);
DECLARE_ATTRIBUTE_NAME(baz);

//pass types and declared attribute names, separated by comma
typedef TupleWithNamedMembers<int, foo,
                              float, quux,
                              double, bar,
                              char, baz
                        > MyTuple;
//extra call to macro "MAKE_TUPLE" can be avoided, see below
class MyConstruct: public MAKE_TUPLE(MyTuple)
{ };

//usage
int main(int argc, char* argv[])
{
    MyConstruct construct;
    construct.foo = 3;
    construct.bar = 5.6;
    construct.quux = 8.9;
    construct.baz = 'h';
    return 0;
}
//一个属性名必须“声明”一次才能使用
//它稍后会出现在任意数量的类声明中
声明属性名称(foo);
声明属性名称(quux);
声明属性名称(条形);
声明属性名称(baz);
//传递类型和声明的属性名称,用逗号分隔
typedef TupleWithNamedMembers MyTuple;
//可以避免对宏“MAKE_TUPLE”的额外调用,如下所示
类MyConstruct:public MAKE_TUPLE(MyTuple)
{ };
//用法
int main(int argc,char*argv[])
{
MyConstruct结构;
construct.foo=3;
构造杆=5.6;
construct.qux=8.9;
construct.baz='h';
返回0;
}
实施:

#ifndef TupleWithNamedMembersH
#define TupleWithNamedMembersH
//---------------------------------------------------------------------------

#include <Loki/typelist.h>
#include <Loki/HierarchyGenerators.h>

template<class T, int a>
struct attribute
{
};

//the generated id is not really unique in all cases
//one should provide better implementation
#define GENERATE_UNIQ_ID(name) ((sizeof(#name)<<16)|__LINE__)

//specializations of the struct "attribute" act like compile-time map between
//a name ID and an attribute name 
#define DECLARE_ATTRIBUTE_NAME_IMPL(name, id) \
    enum { id = GENERATE_UNIQ_ID(name) }; \
    template<class T> \
    struct attribute<T,id> \
    {\
        T name;\
    };
#define DECLARE_ATTRIBUTE_NAME(name)\
    DECLARE_ATTRIBUTE_NAME_IMPL(name, name)

//helps to pass pair of type and name ID as a single type
template<class T, int i>
struct pair
{
    static const int val = i;
    typedef T type;
};

//unpacks compile-time data from PairT and inherits attribute
//with name selected by ID
template<class PairT>
class holder: public attribute<typename PairT::type,PairT::val>
{    };

//turns template arguments into Loki::TypeList
template
<
    typename T1  = Loki::NullType, int i1 = 0, typename T2  = Loki::NullType, int i2 = 0,
    typename T3  = Loki::NullType, int i3 = 0, typename T4  = Loki::NullType, int i4 = 0,
    typename T5  = Loki::NullType, int i5 = 0, typename T6  = Loki::NullType, int i6 = 0,
    typename T7  = Loki::NullType, int i7 = 0, typename T8  = Loki::NullType, int i8 = 0,
    typename T9  = Loki::NullType, int i9 = 0, typename T10 = Loki::NullType, int i10 = 0
>
struct TupleWithNamedMembers
{
public:
    typedef Loki::TL::MakeTypelist<pair<T1,i1>, pair<T2,i2>,
                                   pair<T3,i3>, pair<T4,i4>,
                                   pair<T5,i5>, pair<T6,i6>,
                                   pair<T7,i7>, pair<T8,i8>,
                                   pair<T9,i9>, pair<T10,i10>
                         >::Result Result;
};

//this macro is required because of internal compiler error that I encounter
//Loki::GenScatterHierarchy makes a class inherit every attribute from the type list
#define MAKE_TUPLE(types) Loki::GenScatterHierarchy<types::Result, holder>

#endif //end of "TupleWithNamedMembers.h"
\ifndef TupleWithNamedMembersH
#定义TupleWithNamedMembersH
//---------------------------------------------------------------------------
#包括
#包括
模板
结构属性
{
};
//产生
#ifndef TupleWithNamedMembersH
#define TupleWithNamedMembersH
//---------------------------------------------------------------------------

#include <Loki/typelist.h>
#include <Loki/HierarchyGenerators.h>

template<class T, int a>
struct attribute
{
};

//the generated id is not really unique in all cases
//one should provide better implementation
#define GENERATE_UNIQ_ID(name) ((sizeof(#name)<<16)|__LINE__)

//specializations of the struct "attribute" act like compile-time map between
//a name ID and an attribute name 
#define DECLARE_ATTRIBUTE_NAME_IMPL(name, id) \
    enum { id = GENERATE_UNIQ_ID(name) }; \
    template<class T> \
    struct attribute<T,id> \
    {\
        T name;\
    };
#define DECLARE_ATTRIBUTE_NAME(name)\
    DECLARE_ATTRIBUTE_NAME_IMPL(name, name)

//helps to pass pair of type and name ID as a single type
template<class T, int i>
struct pair
{
    static const int val = i;
    typedef T type;
};

//unpacks compile-time data from PairT and inherits attribute
//with name selected by ID
template<class PairT>
class holder: public attribute<typename PairT::type,PairT::val>
{    };

//turns template arguments into Loki::TypeList
template
<
    typename T1  = Loki::NullType, int i1 = 0, typename T2  = Loki::NullType, int i2 = 0,
    typename T3  = Loki::NullType, int i3 = 0, typename T4  = Loki::NullType, int i4 = 0,
    typename T5  = Loki::NullType, int i5 = 0, typename T6  = Loki::NullType, int i6 = 0,
    typename T7  = Loki::NullType, int i7 = 0, typename T8  = Loki::NullType, int i8 = 0,
    typename T9  = Loki::NullType, int i9 = 0, typename T10 = Loki::NullType, int i10 = 0
>
struct TupleWithNamedMembers
{
public:
    typedef Loki::TL::MakeTypelist<pair<T1,i1>, pair<T2,i2>,
                                   pair<T3,i3>, pair<T4,i4>,
                                   pair<T5,i5>, pair<T6,i6>,
                                   pair<T7,i7>, pair<T8,i8>,
                                   pair<T9,i9>, pair<T10,i10>
                         >::Result Result;
};

//this macro is required because of internal compiler error that I encounter
//Loki::GenScatterHierarchy makes a class inherit every attribute from the type list
#define MAKE_TUPLE(types) Loki::GenScatterHierarchy<types::Result, holder>

#endif //end of "TupleWithNamedMembers.h"
template
<
    typename T1  = Loki::NullType, int i1 = 0, typename T2  = Loki::NullType, int i2 = 0,
    typename T3  = Loki::NullType, int i3 = 0, typename T4  = Loki::NullType, int i4 = 0,
    typename T5  = Loki::NullType, int i5 = 0, typename T6  = Loki::NullType, int i6 = 0,
    typename T7  = Loki::NullType, int i7 = 0, typename T8  = Loki::NullType, int i8 = 0,
    typename T9  = Loki::NullType, int i9 = 0, typename T10 = Loki::NullType, int i10 = 0
>
struct MakeTupleWithNamedMembers
{
private:
    typedef Loki::TL::MakeTypelist<pair<T1,i1>, pair<T2,i2>,
                                   pair<T3,i3>, pair<T4,i4>,
                                   pair<T5,i5>, pair<T6,i6>,
                                   pair<T7,i7>, pair<T8,i8>,
                                   pair<T9,i9>, pair<T10,i10>
                         >::Result type_list;
public:
    typedef Loki::GenScatterHierarchy<type_list, holder> Result;
};

//usage
class MyConstruct: public MakeTupleWithNamedMembers<int, foo, float, quux>::Result
{ };