Руководство по выводу шаблона функции-члена или другой метод, позволяющий компилятору знать, как вызывать функцию - PullRequest
0 голосов
/ 07 февраля 2019
struct setup_entry 
{
    template< typename T >
    void Disable( bool(*p)(T*) ) { ... }
}

Выключение вызова:

setup_entry X;

Case 1: X.Disable( [](int*)->bool{...} );        //FAIL to deduce T
Case 2: X.Disable<int>( [](int*)->bool{...} );   //OK   to deduce T

Я хотел бы использовать вариант 1. (Легче для пользователя)

Есть идеи?


Упрощенное окончательное решение для записи заключалось в следующем:

template< typename T >
void Disable( T&& Callback )
{ 
   auto p = +Callback;
   ...
}

Ответы [ 2 ]

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

Сначала вы должны знать, что тип [](int*) -> bool {...} это , а не просто bool(int*) или bool(*)(int*);это уникальный тип замыкания, преобразуемый в bool(*)(int*).

. И этот тип не выводим в этом контексте.

Решение: явно выполните преобразование.

X.Disable( static_cast<bool(*)(int*)>([](int*) -> bool {...}) );

Лучшее решение: как @ Какой-то программист чувак говорит, используйте шаблон или используйте std::function.Например:

template <typename F>
void Disable(F f)
{
    static_assert(std::is_invocable_r_v<bool, F, int*>, "your message here"); // if you want to ensure that the function is actually valid
    // ...
}

Или:

void Disable(std::function<bool(int*)> f) { ... }
0 голосов
/ 07 февраля 2019

Вы не можете этого сделать, потому что неявное преобразование (из лямбды в указатель на функцию) не будет учитываться при выводе аргумента шаблона ;T не может быть выведено.

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

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

X.Disable(+[](int*)->bool{...} ); 
//        ^

или

X.Disable(static_cast<bool(*)(int*)>([](int*)->bool{...}));
...