C++11 не выводит тип, когда задействованы функции std::function или lambda

Когда я определяю эту функцию,

template<class A>
set<A> test(const set<A>& input) {
    return input;
}

я могу вызвать ее, используя test(mySet)в другом месте кода. код без необходимости явно определять тип шаблона. Однако, когда я использую следующую функцию:

template<class A>
set<A> filter(const set<A>& input,function<bool(A)> compare) {
    set<A> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret.insert(*it);
        }
    }
    return ret;
}

Когда я вызываю эту функцию, используя filter(mySet,[](int i) { return i%2==0; }); Я получаю следующую ошибку:

ошибка: нет соответствующей функции для вызова 'filter(std::set&, main()::)'

Однако все эти версии работают :

std::function<bool(int)> func = [](int i) { return i%2 ==0; };
set<int> myNewSet = filter(mySet,func);

set<int> myNewSet = filter<int>(mySet,[](int i) { return i%2==0; });

set<int> myNewSet = filter(mySet,function<bool(int)>([](int i){return i%2==0;}));

Почему c++11 не может угадать тип шаблона, когда я помещаю лямбда-функцию непосредственно в выражение без непосредственного создания std::function?

РЕДАКТИРОВАТЬ:

По совету Люка Дантона в комментариях, вот альтернатива функции, которую я использовал ранее, которая не требует явной передачи шаблонов.

template<class A,class CompareFunction>
set<A> filter(const set<A>& input,CompareFunction compare) {
    set<A> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret.insert(*it);
        }
    }
    return ret;
}

Это можно вызвать с помощью set result = filter(myIntSet,[](int i) { i % 2 == 0; });без использования шаблона.

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

template<class Value,class CompareType,class IndexType>
auto filter(const set<Value>& input,CompareType compare,IndexType index) -> map<decltype(index(*(input.begin()))),Value> {
    map<decltype(index(*(input.begin()))),Value> ret;
    for(auto it = input.begin(); it != input.end(); it++) {
        if(compare(*it)) {
            ret[index(*it)] = *it;
        }
    }
    return ret;
}

Ее также можно вызывать без прямого использования шаблона, как

map<string,int> s = filter(myIntSet,[](int i) { return i%2==0; },[](int i) { return toString(i); });
54
задан Micha Wiedenmann 2 March 2018 в 05:40
поделиться