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