Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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 - Fatal编程技术网

C++ 如何创建类型化参数包类?

C++ 如何创建类型化参数包类?,c++,templates,C++,Templates,我需要在一个类中打包任意类型的固定数量的值。然后我需要能够根据每个参数的类型通过一个开关来传递它们。参数的类型是基本的C类型和指向stuff的指针(一个特定且数量有限的“stuff”),所以并不复杂 该“参数”类需要是轻的(在空间和处理中) 这是我需要如何使用它的一个示例: void MyFunc( const Parameters &Params ) { // for loop switch( Params(0).GetType() ) { case MY_INT_TYPE: in

我需要在一个类中打包任意类型的固定数量的值。然后我需要能够根据每个参数的类型通过一个开关来传递它们。参数的类型是基本的C类型和指向stuff的指针(一个特定且数量有限的“stuff”),所以并不复杂

该“参数”类需要是轻的(在空间和处理中)

这是我需要如何使用它的一个示例:

void MyFunc( const Parameters &Params )
{
// for loop
switch( Params(0).GetType() ) {
  case MY_INT_TYPE: int ValInt = Params(0).Get<int>(); ...
  case MY_PTR_TO_MY_STUFF1: MyStuff1 *ValS1 = Params(0).Get<MyStuff1*>(); ...
  ...
  }
}

Parameters MyParams(2);
MyParams.Set<int>(0, 123);
MyParams.Set<MyStuff1*>(1, &SomeClassInstance);
MyFunc( MyParams );
...
MyParams.Set<float>(0, 123.456);  // The same variable in the same scope
MyParams.Set<int*>(1, &Val);
MyFunc( MyParams );
void MyFunc(常量参数和参数)
{
//for循环
开关(参数(0).GetType()){
大小写MY_INT_TYPE:INT ValInt=Params(0).Get()。。。
case MY_PTR_TO_MY_stuf1:mystuf1*ValS1=Params(0).Get()。。。
...
}
}
参数MyParams(2);
MyParams.Set(0123);
MyParams.Set(1,&SomeClassInstance);
MyFunc(MyParams);
...
MyParams.Set(0123.456);//同一范围内的同一变量
MyParams.Set(1,&Val);
MyFunc(MyParams);
当然,我可以手动专门处理所有类型并存储在联合中,这就是蛮力方法。我一直在想有一种更简单的方法可以做到这一点,但我想不出来。我可以使用类型特征来存储类型信息,但是我被值卡住了。铸造价值不是一种选择


如果不使用运行时多态性,那么任何指针(即象征性指针)

无论如何,都会同时有一个开关。如果要使用静态多态性,则需要专门化或切换

使用type2enum和enum2type映射的好方法是:

type2enum:

// preparition
template<class T> type2enum();
#define TYPE2ENUM_SPEC(TYPE, ENUM) \
template<> type2enum<TYPE>() \
{ return ENUM; }

enum { T1enum, T2enum, T3enum }
TYPE2ENUM_SPEC(type1_t, T1enum);
TYPE2ENUM_SPEC(type2_t, T2enum);
TYPE2ENUM_SPEC(some_third_type_t, T3enum);
然后将其用于将类型映射到枚举:

int typeId = type2enum<Type1>();
int-typeId=type2enum();
或要键入的常量枚举:

typedef Enum2Type<ConstEnumType>::type_t some_t;
typedef Enum2Type::type_t some_t;
对于要键入的运行时枚举,您可以使用以下内容:

template<class ObjT>
void DoWithTypeIdValue(int enumValue, const ObjT& obj)
{
    switch(enumValue)
    {
       case enumType1:
           obj.do<Enum2Type<enumType1>::type_t>();
           break;
       case enumType2:
           obj.do<Enum2Type<enumType2>::type_t>();
           break;
       case enumType3:
           obj.do<Enum2Type<enumType3>::type_t>();
           break;
       default:
           assert(!"Unknown type constant");
    }
}
模板
void DoWithTypeIdValue(整数枚举值、常量ObjT和obj)
{
开关(枚举值)
{
案例1:
obj.do();
打破
案例2:
obj.do();
打破
案例3:
obj.do();
打破
违约:
断言(!“未知类型常量”);
}
}

无论如何,如果不使用运行时多态性,将立即有一个开关。如果要使用静态多态性,则需要专门化或切换

使用type2enum和enum2type映射的好方法是:

type2enum:

// preparition
template<class T> type2enum();
#define TYPE2ENUM_SPEC(TYPE, ENUM) \
template<> type2enum<TYPE>() \
{ return ENUM; }

enum { T1enum, T2enum, T3enum }
TYPE2ENUM_SPEC(type1_t, T1enum);
TYPE2ENUM_SPEC(type2_t, T2enum);
TYPE2ENUM_SPEC(some_third_type_t, T3enum);
然后将其用于将类型映射到枚举:

int typeId = type2enum<Type1>();
int-typeId=type2enum();
或要键入的常量枚举:

typedef Enum2Type<ConstEnumType>::type_t some_t;
typedef Enum2Type::type_t some_t;
对于要键入的运行时枚举,您可以使用以下内容:

template<class ObjT>
void DoWithTypeIdValue(int enumValue, const ObjT& obj)
{
    switch(enumValue)
    {
       case enumType1:
           obj.do<Enum2Type<enumType1>::type_t>();
           break;
       case enumType2:
           obj.do<Enum2Type<enumType2>::type_t>();
           break;
       case enumType3:
           obj.do<Enum2Type<enumType3>::type_t>();
           break;
       default:
           assert(!"Unknown type constant");
    }
}
模板
void DoWithTypeIdValue(整数枚举值、常量ObjT和obj)
{
开关(枚举值)
{
案例1:
obj.do();
打破
案例2:
obj.do();
打破
案例3:
obj.do();
打破
违约:
断言(!“未知类型常量”);
}
}

另一种摆脱开关的方法是使用枚举和函子数组:

enum TheTypes { T1, T2, T3, TheTypesCount};

boost::function<void (const Parameters &Params)> Processors[] = {
    boost::bind(&T1::ProcessingMethod, t1Obj, _1),
    boost::bind(&T2::ProcessingStaticMethod, _1),
    boost::bind(RawFunction, _1)
};
祝贺你

如果你是疯子,我们将讨论下一种方法。 如何创建静态装饰器(mixin),以便自动执行以下操作:

  • 索引特征
  • 存储特征处理函子
  • 形成一系列特征

另一种允许去掉开关的方法是使用枚举和函子数组:

enum TheTypes { T1, T2, T3, TheTypesCount};

boost::function<void (const Parameters &Params)> Processors[] = {
    boost::bind(&T1::ProcessingMethod, t1Obj, _1),
    boost::bind(&T2::ProcessingStaticMethod, _1),
    boost::bind(RawFunction, _1)
};
祝贺你

如果你是疯子,我们将讨论下一种方法。 如何创建静态装饰器(mixin),以便自动执行以下操作:

  • 索引特征
  • 存储特征处理函子
  • 形成一系列特征

关于你最后的评论,我给你下一个答案:)

类参数处理器
{
//T1类型的自定义参数接收器
模板
公共参数处理器和输入(常数T1和o)
{ ... } 
//T2类型的自定义参数接收器
模板
公共参数处理器和in(T2)
{ ... } 
//默认参数接收器
模板
公共参数处理器和操作员(const T&o)
{
//如果项目允许,可以使用一些通用方法
...
归还这个
} 
无效过程()
{ ... }
};
副处理器;
pp.in(0123)
.in(0123.456)
.in.(“asds”);
.Process();
如果每个重载都能自行处理,那当然更好了。
我真的希望我的回答能满足你的需要

关于你最后的评论,我给你下一个答案:)

类参数处理器
{
//T1类型的自定义参数接收器
模板
公共参数处理器和输入(常数T1和o)
{ ... } 
//T2类型的自定义参数接收器
模板
公共参数处理器和in(T2)
{ ... } 
//默认参数接收器
模板
公共参数处理器和操作员(const T&o)
{
//如果项目允许,可以使用一些通用方法
...
归还这个
} 
无效过程()
{ ... }
};
副处理器;
pp.in(0123)
.in(0123.456)
.in.(“asds”);
.Process();
如果每个重载都能自行处理,那当然更好了。
我真的希望我的回答能满足你的需要

理想的实现将使用由有效参数类型集参数化的变量类型(例如,
boost::variant
)。下面是一个如何使用变体类型解决问题的示例:

typedef Variant<int, MyStuff1*> Parameter;

int main()
{
    MyStuff1 SomeClassInstance;

    Parameter MyParams[2] = { 123, &SomeClassInstance };

    int ValInt = MyParams[0].Get<int>();
    MyStuff1* ValS1 = MyParams[1].Get<MyStuff1*>();
}

这个实现只是一个示例,只支持两种类型——扩展到支持更多类型相对容易。您可能希望使用模板参数包和移动构造函数来实现最干净、最高效的实现。

理想的实现将使用由有效参数类型集参数化的变量类型(例如,
boost::variant
)。下面是一个如何使用变体类型解决问题的示例:

typedef Variant<int, MyStuff1*> Parameter;

int main()
{
    MyStuff1 SomeClassInstance;

    Parameter MyParams[2] = { 123, &SomeClassInstance };

    int ValInt = MyParams[0].Get<int>();
    MyStuff1* ValS1 = MyParams[1].Get<MyStuff1*>();
}
这个实现只是一个示例,只支持两种类型——扩展到su相对容易