假设我有许多枚举enum EnumA { fooA, barA, quuzA };
,enum EnumB {fooB, barB, quuzB };
等,并且表格中有许多模板结构:
template<EnumA value> struct StructA {};
template<EnumB value> struct StructB {};
依此类推。我希望实现从枚举值到相应结构的隐式转换,显然当枚举值是编译时常量时。
对于更多上下文,我希望能够在如下的上下文中使用它。我有一个功能
template<typename T> void somefunc(int somepar, T);
我可以将其用作somefunc(somepar, StructB<quuzB>());
,我希望能够将其用作somefunc(somepar, quuzB);
。
(并且,不,将somefunc重载为一组模板函数,每个枚举一个,执行适当的结构包装本身不是一个选项,因为(1)枚举的数量和(2)我的事实我还希望将template<typename T1, typename T2> void somefunc(int par1, T1, int par2, T2)
用作somefunc(p1, StructB<quuzB>(), p2, StructA<barA>())
等等。)
答案 0 :(得分:2)
您希望在通话中作为语法参数提供的enum
值最终为运行时值。但是要将其转换为特定于值的类型,需要编译时间了解该值。目前,您手动提供编译时知识,并且使用您提出的更简单的调用语法,获取该知识的唯一一般方法是通过一些源代码预处理。
为了避免预处理(通过任何方式,例如宏或脚本或经过训练的黑猩猩),您可以调整对调用语法的要求,例如:显式提供enum
类型,而不是
somefunc( somepar, quuzB );
......你会写
somefunc<EnumB, quuzB>( somepar );
示例,宏的东西仅用于展示,如果你想要的话,但我建议不要使用宏(显式好,隐式坏):
enum EnumA { fooA, barA, quuzA };
enum EnumB { fooB, barB, quuzB };
template< EnumA value> struct StructA {};
template< EnumB value> struct StructB {};
//template<typename T> void somefunc( int somepar, T );
template< class Enum_type, Enum_type value >
void somefunc( int somepar );
void foo()
{
somefunc<EnumB, quuzB>( 42 );
}
//-------------------------------------------------------------
#define SOMEFUNC( par, e ) somefunc<decltype(e), e>( par )
void bar()
{
SOMEFUNC( 42, quuzB );
}
//-------------------------------------------------------------
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
#ifdef __GNUC__
# include <cxxabi.h>
auto demangled( char const name[] )
-> string
{
int status = 0;
char* c_result = abi::__cxa_demangle( name, 0, 0, &status);
string result = c_result;
free( c_result );
return result;
}
#else
auto demangled( char const name[] )
-> string
{ return name; }
#endif
template< class Type >
void somefunc_impl( int x, Type )
{
cout << x << ", " << demangled( typeid( Type ).name() ) << endl;
}
template< class Enum_type >
struct Enum_to_struct;
template<>
struct Enum_to_struct<EnumA>
{
template< EnumA e > struct Struct{ using T = StructA<e>; };
};
template<>
struct Enum_to_struct<EnumB>
{
template< EnumB e > struct Struct{ using T = StructB<e>; };
};
template< class Enum_type, Enum_type value >
void somefunc( int somepar )
{
using Struct = typename Enum_to_struct<Enum_type>::template Struct<value>::T;
somefunc_impl( somepar, Struct() );
}
auto main() -> int
{
foo();
bar();
}
这可以简化 - 您可以避免Enum_to_struct
特征 - 使用部分专业的类模板,而不是像StructA
和StructB
enum EnumA { fooA, barA, quuzA };
enum EnumB { fooB, barB, quuzB };
template< class Enum_type, Enum_type value >
struct Struct{};
template< EnumA e >
struct Struct< EnumA, e > {}; // Whatever, corresponding to StructA
template< class Enum_type, Enum_type value >
void somefunc( int somepar );
void foo()
{
somefunc<EnumB, quuzB>( 42 );
}
//-------------------------------------------------------------
#define SOMEFUNC( par, e ) somefunc<decltype(e), e>( par )
void bar()
{
SOMEFUNC( 42, quuzB );
}
//-------------------------------------------------------------
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
#ifdef __GNUC__
# include <cxxabi.h>
auto demangled( char const name[] )
-> string
{
int status = 0;
char* c_result = abi::__cxa_demangle( name, 0, 0, &status);
string result = c_result;
free( c_result );
return result;
}
#else
auto demangled( char const name[] )
-> string
{ return name; }
#endif
template< class Type >
void somefunc_impl( int x, Type )
{
cout << x << ", " << demangled( typeid( Type ).name() ) << endl;
}
template< class Enum_type, Enum_type value >
void somefunc( int somepar )
{
somefunc_impl( somepar, Struct<Enum_type, value>() );
}
auto main() -> int
{
foo();
bar();
}
为了完整性,即使宏是Evil™而且我建议不要使用它们,如果你选择使用宏路径,你可以减少单个宏的开销,而不是每个功能一个,不太明显的调用语法成本:
#define TV( v ) decltype( v ), v
void qwepoi()
{
somefunc<TV( quuzB )>( 42 );
}