Операция условного типа во время компиляции с макросами - PullRequest
0 голосов
/ 10 февраля 2019

Я пытаюсь создать макрос, упрощающий что-то в зависимости от типа параметра.

Для простоты мы будем говорить, что типы - это строки в стиле 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?

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

C ++ имеет перегрузку, поэтому, возможно, вы могли бы просто сделать:

inline int Function( const char* input ){ return FunctionA(input); }
inline int Function( const wchar_t* input ){ return FunctionB(input); }

вместо макроса.

0 голосов
/ 10 февраля 2019

Первый подход:

Тернарные операторы с сравнениями типов.&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 .Но я думаю, что первое безопаснее для вашего случая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...