Ale to nie wyjaśnia, dlaczego nie może dopasować parametru.
Odliczenie szablonów dokładnie dopasowuje typy. Jeśli nie można wywnioskować typów, odliczenie nie powiedzie się. Konwersje nigdy nie są brane pod uwagę.
W wyrażeniu:
qux(ts, [](const T&) { return 42; });
typu ekspresji lambda pewne unikalny, Nienazwana typu. Jakikolwiek jest ten typ, to na pewno nie jest to To(const From&)
- więc dedukcja się nie udaje.
Jeśli zrobię qux
funkcję non-szablon, zastępując From
z T
i To
z int
, kompiluje.
To nie jest prawda. Jednakże, jeśli argumentem byłby wskaźnik do funkcji, a nie jako odniesienie do funkcji, to byłby. Dzieje się tak, ponieważ lambda bez przechwytywania jest niejawnie przekształcalna na równoważny typ wskaźnika funkcji. Ta konwersja jest dozwolona poza kontekstem dedukcji.
template <class From, class To>
void func_tmpl(From(*)(To)) { }
void func_normal(int(*)(int)) { }
func_tmpl([](int i){return i; }); // error
func_tmpl(+[](int i){return i; }); // ok, we force the conversion ourselves,
// the type of this expression can be deduced
func_normal([](int i){return i; }); // ok, implicit conversion
Jest to ten sam powód, dlaczego to się nie powiedzie:
template <class T> void foo(std::function<T()>);
foo([]{ return 42; }); // error, this lambda is NOT a function<T()>
Ale to udaje:
void bar(std::function<int()>);
bar([]{ return 42; }); // ok, this lambda is convertible to function<int()>
Korzystnym rozwiązaniem byłoby wywnioskować typ wymagalne i wybierz wynik, używając: std::result_of
:
template <class From,
class F&&,
class To = std::result_of_t<F&&(From const&)>>
void qux(std::vector<From> const&, F&&);
Teraz możesz w prosty sposób przekazać obiekt lambda, funkcję lub funkcję.
Przede wszystkim 'qux' nie zwraca niczego, więc to nie powinno kompilować' auto bar = qux ... ' – nbro
@nbro To nie ma nic wspólnego z problemem w zasięgu ręki. – emlai
Jeśli wiesz tak bardzo, nie zadałbyś pytania. W każdym razie, przegłosowano, ponieważ nie wiem też dlaczego. – nbro