如何实现枚举值到类模板的隐式转换
How to achieve implicit conversion from enum value to class template
假设我有一些枚举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>())
等)
您希望在调用中作为实际参数提供的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();
}
为了完整起见,即使宏是邪恶的™我不建议使用它们,如果你选择宏路径,你可以将开销减少到单个宏而不是每个函数一个宏,代价是调用语法不太明显:
#define TV( v ) decltype( v ), v
void qwepoi()
{
somefunc<TV( quuzB )>( 42 );
}
- 为 Sql 服务器实现 odbc 包装器.将数据库数据读取为字符或要求驱动程序将数据转换为 C 类型
- 独立于实现的浮点/整数转换
- 在调用函数上实现C++转换
- 实现可以<T>转换为 Stream 的 Stream,<U>其中 U 是 T 的基数
- 如何实现相互强制转换
- 是否可以实现自动全局转换
- 如何将 std::array<double, 100> 转换为 std::array<float, 100> ?(避免明显的样板实现)
- 无法在 IOS 中将常量字符 * 表[] 转换为 NSArray 以实现统一
- 转换为链接切割树的C 实现
- 两种类型转换有何不同?
- 在没有 const 强制转换的链表中实现高级方法
- 如何将 GLCM 的实现转换为 Java C++
- 优先级队列实现为单一链接,无法更新插入的指针转换
- 了解C++位操作中的二进制转换实现
- std::tuple的实现是否允许在触发空类元素的派生到基转换时失败
- 如何为涉及对象成员、间接寻址和强制转换的排序算法实现lambda函数
- 高效的无符号到签名转换,避免实现定义的行为
- 如何在Python中实现ITK映像和SimpleItk图像之间的转换
- 智能指针实现的隐式强制转换
- 如何将表驱动的 CRC 实现转换为按位实现