您想在调用中作为实际参数提供的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 );
}