2014-06-18 8 views
5

Sto cercando di fare una funzione che trova l'elemento minimo in una gamma che soddisfa una determinata condizione:Impossibile dedurre dei parametri modello dal argomento di default del parametro di funzione

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

ma ottengo questo errore:

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 non è il tipo di ritorno, in modo che non sta cercando di dedurre il tipo di ritorno, e non mi pare che ci siano sovraccarichi ambigue di Comp (dal momento che non ci può essere un solo tipo di ritorno di dereferenziazione uno It). Perché ricevo questo errore e come posso risolverlo?

+2

Non è possibile dedurre parametri di modello da argomenti in default. – ghostofstandardspast

+1

[OT]: la tua implementazione è UB come fai 'comp (* it, * end)'. – Jarod42

risposta

8

vi aspettate il parametro modello Comp essere dedotta dalla argomento di default che hai fornito per la funzione corrispondente parametro. Tuttavia, ciò è esplicitamente indicato come un contesto non dedotto, il che significa modello argomento deduzione non riuscirà per quel parametro modello (a meno che non si può dedurre da altrove).

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

Per avere la detrazione modello di argomentazione successo, fornire un argomento di default per il parametro del modello, al posto del parametro di funzione.

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

questo funziona per me:

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

Si consiglia il seguente:

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