I'm trying to make a function which finds the minimum element in a range which satisfies a given condition:
#include <functional>
#include <iostream>
#include <vector>
template <typename It, typename Pred, typename Comp>
It minElementWhere(
It begin,
It end,
Pred pred = Pred(),
// Use less-than as the default comparator.
Comp comp = std::less<decltype(*std::declval<It>())>()
) {
It minElement = end;
for (It it = begin; it != end; ++it) {
if (!pred(*it)) {
continue;
}
if (comp(*it, *minElement)) {
minElement = it;
}
}
return minElement;
}
int main() {
std::vector<double> foo;
foo.push_back(6);
foo.push_back(10);
foo.push_back(-3);
foo.push_back(7);
std::cout << *minElementWhere(
foo.begin(),
foo.end(),
[](double val) {
return val >= 0;
}
) << std::endl;
}
But I get this error:
main.cpp: In function 'int main()':
main.cpp:40:5: error: no matching function for call to 'minElementWhere(std::vector<double>::iterator, std::vector<double>::iterator, main()::__lambda0)'
) << std::endl;
^
main.cpp:40:5: note: candidate is:
main.cpp:6:4: note: template<class It, class Pred, class Comp> It minElementWhere(It, It, Pred, Comp)
It minElementWhere(
^
main.cpp:6:4: note: template argument deduction/substitution failed:
main.cpp:40:5: note: couldn't deduce template parameter 'Comp'
) << std::endl;
Comp
isn't the return type, so it's not trying to deduce the return type, and it doesn't seem to me like there are ambiguous overloads of Comp
(since there can only be one return type of dereferencing an It
). Why am I getting this error, and how can I fix it?
You're expecting the template parameter Comp
to be deduced from the default argument you provided for the corresponding function parameter. However, this is explicitly listed as a non-deduced context, meaning template argument deduction will fail for that template parameter (unless it can be deduced from elsewhere).
From §14.8.2.5/5 [temp.deduct.type]
The non-deduced contexts are:
— ...
— A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
To have template argument deduction succeed, provide a default argument for the template parameter, instead of the function parameter.
template <typename It,
typename Pred,
typename Comp = std::less<decltype(*std::declval<It>())>>
It minElementWhere(
It begin,
It end,
Pred pred = Pred(),
Comp comp = Comp()
) {
...
}
Live demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With