Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
707 views
Welcome To Ask or Share your Answers For Others

1 Answer

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...