Первый подход:
Тернарные операторы с сравнениями типов.&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)
с использованием clang с -O2
, как показано на godbolt .Но я думаю, что первое безопаснее для вашего случая.