我正在尝试创建一个根据参数类型简化为某种宏的宏。
为简单起见,我们将类型称为c样式字符串。情况如下:
int FunctionA( const char* input );
int FunctionB( const wchar_t* input );
#define Function( input ) \
input is of type char \
FunctionA( input ) \
input is of type wchar_t \
FunctionB( input )
// is there something else I can do to simplify this operation at compile time?
// maybe somehow use decltype( input ) to narrow which function to use?
// maybe if constexpr ( input ) or something? is there a constexpr version of the ?: operator?
// maybe std::is_same?
主要问题是,它必须替代可以作为参数传递的内容。分号不起作用。
例如
Foo( Function( "Example" ) );
使用C ++ 17我有哪些选择?
答案 0 :(得分:1)
第一种方法:
具有typeid比较的三元运算符。 &input[0]
是一种古老的C技巧,用于将X元素数组的类型分解为类型的指针(我们也可以使用input + 0
)。 reinterpret_cast
用于在转换指针时使警告/错误消失。
#define Function(input) \
( \
typeid(&input[0]) == typeid(const char*) || \
typeid(&input[0]) == typeid(char*) \
) ? ( \
FunctionA(reinterpret_cast<const char*>(input)) \
) : ( \
typeid(&input[0]) == typeid(const wchar_t*) || \
typeid(&input[0]) == typeid(wchar_t*) \
) ? ( \
FunctionB(reinterpret_cast<const wchar_t*>(input)) \
) : ( \
assert(0), \
0 \
)
void main1() {
Foo(Function("Example"));
}
第二种方法:
具有特殊实例化的模板:
template<typename T> inline int
Function2(T t);
template<> inline int
Function2<const char*>(const char* t) {
return FunctionA(t);
}
template<> inline int
Function2<const wchar_t*>(const wchar_t* t) {
return FunctionB(t);
}
void main2() {
Foo(Function2("Example"));
}
两个代码都编译为:
push rax
mov edi, offset .L.str
call FunctionA(char const*)
mov edi, eax
pop rax
jmp Foo(int)
与-O2
一起使用clang,如godbolt所示。但是我想第一个对于您的情况更安全。
答案 1 :(得分:0)
C ++具有重载,因此也许您可以简单地做到这一点:
inline int Function( const char* input ){ return FunctionA(input); }
inline int Function( const wchar_t* input ){ return FunctionB(input); }
代替宏。