C++ 如何实现枚举值到类模板的隐式转换

C++ 如何实现枚举值到类模板的隐式转换,c++,enums,type-conversion,implicit-conversion,C++,Enums,Type Conversion,Implicit Conversion,假设我有许多enumenum EnumA{fooA,barA,quoza},enum EnumB{fooB,barB,quzb},等等,以及以下形式的许多模板结构: template<EnumA value> struct StructA {}; template<EnumB value> struct StructB {}; template struct StructA{}; 模板结构StructB{}; 等等等等。我希望实现从枚举值到相应结构的隐式转换,显然,当

假设我有许多enum
enum EnumA{fooA,barA,quoza}
enum EnumB{fooB,barB,quzb},等等,以及以下形式的许多模板结构:

template<EnumA value> struct StructA {};
template<EnumB value> struct StructB {};
template struct StructA{};
模板结构StructB{};
等等等等。我希望实现从枚举值到相应结构的隐式转换,显然,当枚举值是编译时常量时

对于更多的上下文,我希望能够在如下上下文中使用它。我有一个函数

template<typename T> void somefunc(int somepar, T);
模板void somefunc(int somepar,T);
我可以使用它作为
somefunc(somepar,StructB())并且我希望能够将其用作
somefunc(somepar,quzb)取而代之


(不,将somefunc重载为一组模板函数,每个枚举一个,并进行适当的结构包装本身不是一个选项,因为(1)枚举的数量和(2)我还希望将类似
template void somefunc(int par1,T1,int par2,T2)
的内容用作
somefunc(p1,StructB(),p2,StructA())
等)

要在调用中作为实际参数提供的
enum
值以运行时值结束。但要将其转换为特定于值的类型,需要编译时了解该值。目前,您正在手动提供编译时知识,使用您建议的更简单的调用语法,获取这些知识的唯一通用方法是通过一些源代码预处理

为了避免预处理(通过任何方式,例如宏或脚本,或训练有素的黑猩猩),您可以调整调用语法的要求,例如显式提供
enum
类型,而不是

somefunc( somepar, quuzB );
……你会写信的

somefunc<EnumB, quuzB>( somepar );

为了完整性,即使宏是邪恶的™ 我建议不要这样做,如果您选择使用宏路径,您可以将开销减少到单个宏,而不是每个函数一个宏,但代价是调用语法不太明显:

#define TV( v ) decltype( v ), v

void qwepoi()
{
    somefunc<TV( quuzB )>( 42 );
}
#定义电视(v)decltype(v),v
void qwepoi()
{
somefunc(42);
}

如果您的代码与本例相同,请注意
fooA==fooB
(两者都是
int
s),因此调用
somefunc(42,fooA)
是不可能解决的。您可以使用
enum类
es来消除歧义。是的,代码是原样的。我希望,考虑到编译器在大多数上下文中都能很好地区分枚举,它也能解决这个问题。我猜使用C++11中的枚举类可能会对它做些什么,但不使用C++98中的普通枚举?至少在理论上,使用C++11
enum类
es是可能的。但是我不知道如何实现它。另外,
enum类
es需要名称空间,因此在详细性方面不会有太大好处8-/考虑到整个要点是为
somefunc
的用户获得更好、更简单的语法,并且考虑到,正如您提到的,参数值(即使在调用位置知道编译时)是函数的运行时,恐怕不进行预处理就不可能找到一个具有“nice”语法的解决方案,所以我不得不这样做。(续)您提出的其他解决方案与我已经放弃的解决方案非常相似,因为语法不能很好地扩展到多参数对的情况(比较
somefunc(42,quuzB,32,barA)
vs
somefunc(42,32)
)。我非常感谢您的努力,但在这种情况下,我似乎无法逃避宏方法来实现良好的语法。非常感谢您从本质上确认我所希望的无法实现;-)
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();
}
#define TV( v ) decltype( v ), v

void qwepoi()
{
    somefunc<TV( quuzB )>( 42 );
}