2014-06-18 18 views
5

Próbuję utworzyć funkcję, która wyznaczy minimalną elementu w zakresie, które spełniają podany warunek:Nie można wywnioskować parametr szablonu z domyślnym argumentem funkcji parametru

#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; 
} 

Ale otrzymuję ten błąd:

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 nie jest typem powrotu, więc nie próbuje wywnioskować typ zwracany, a nie wydaje mi się, że są niejednoznaczne przeciążenia Comp (ponieważ nie może być tylko jeden typ powrót dereferencing It). Dlaczego pojawia się ten błąd i jak mogę to naprawić?

+2

To nie jest możliwe, aby wydedukować parametry szablonu z niewykonaniem argumentów. – ghostofstandardspast

+1

[OT]: twoja implementacja to UB, tak jak robisz "comp (* it, * end)". – Jarod42

Odpowiedz

8

czekasz parametr szablonu Comp zostać wyprowadzona z domyślnym argumentem podany dla odpowiedniej funkcji parametr. Jest to jednak jawnie wyszczególnione jako niedomykowany kontekst, co oznacza, że ​​odrzucenie argumentu szablonu nie powiedzie się dla tego parametru szablonu (chyba że można go wywnioskować z innych źródeł).

Od §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.

Aby odliczenie szablon argumentem uda, dostarcza domyślną argumentu dla parametru szablonu, zamiast parametru funkcji.

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

1

Działa to dla mnie:

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() 
) { 
    It minElement = end; 

    for (It it = begin; it != end; ++it) { 
     if (!pred(*it)) { 
      continue; 
     } 

     if (comp(*it, *minElement)) { 
      minElement = it; 
     } 
    } 

    return minElement; 
} 
2

Możesz chcieć następujące:

#include <iterator> 
struct always_true{ 
    template<typename T> 
    bool operator()(T&& val) const{ 
     return true; 
    } 
}; 

template < 
    typename It, 
    typename Pred = always_true, 
    typename Comp = std::less<typename std::iterator_traits<It>::value_type > 
> 
It minElementWhere(
    It begin, 
    It end, 
    Pred pred = Pred(), 
    Comp comp = Comp() 
    ){ 
    It minElement = end; 

    for (It it = begin; it != end; ++it) { 
     if (pred(*it) && (minElement == end || comp(*it, *minElement))){ 
      minElement = it; 
     } 
    } 

    return minElement; 
} 
Powiązane problemy