Аргумент указателя функции C ++ с шаблоном - PullRequest
9 голосов
/ 05 июня 2019

Я пытаюсь использовать указатель на функцию с шаблоном в качестве аргумента. Но компилятору, похоже, не удается обработать лямбду и нульптр.

Все нормально, когда я изменяю void (*callback)(T input) на void (*callback)(int input) в следующем коде.

Определяется ли это поведение компилятора стандартом C ++?

Я использую команду компиляции $ g++ main.cpp -std=c+11, но в Visual Studio 2019 такое же поведение.

template <class T>
int dummy (T tmp, void (*callback)(T input)) {
    // Doesn't do anything, just trying to compile
    // If I change (T input) to (int input), it compiles fine  
    if (callback)
        return 1;
    else
        return 0;
}

void callback (int input) {
    return;
}

int main () {
    int tmp = 10;
    auto callback_lambda = [](int input) -> void {
        return;
    };

    dummy(tmp, callback); // Compiles OK
    dummy(tmp, callback_lambda); // Error: mismatched types 'void (*)(T)' and 'main()::<lambda(<int>)'
    dummy(tmp, nullptr); // Error: no matching function for call to 'dummy(int&, std:nullptr_t)'
    return 0;
}        

1 Ответ

6 голосов
/ 05 июня 2019

Проблема в том, что неявное преобразование не будет учитываться при выводе аргумента шаблона .

При выводе типа не учитываются неявные преобразования (кроме корректировок типа, перечисленных выше):это работа для разрешения перегрузки , которое произойдет позже.

Так что при передаче лямбды и nullptr преобразования в указатель функции не учитываются, параметр шаблона T не может быть выведен для 2-го аргумента функции, а затем вызывает ошибку.

Вы можете сделать 2-й параметр функции равным неизведанному контексту , чтобы исключить его из вывода, с помощьюсправка std::type_identity.

type_identity может использоваться для блокировки вывода аргумента шаблона :

например

template <class T>
int dummy (T tmp, void (*callback)(std::type_identity_t<T>)) {
    ...
}

LIVE

PS: если ваш компилятор не поддерживает std::type_identity (начиная с C ++ 20), вы можетеопределите свою версию, это не сложно.

...