Когда я определяю эту функцию,
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; });
Я получаю следующую ошибку:
error: нет соответствующей функции для вызова "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;}));
Почему С++ 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<int> result = filter(myIntSet,[](int 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); });