Domanda

Ho giocato con i funzioni in C ++. In particolare, ho un vettore di coppie che vorrei ordinare in base al primo elemento della coppia. Ho iniziato a scrivere un funzione completamente specializzato (ovvero qualcosa come "bool MyLessThan (MyPair & amp; lhs, MyPair & amp; rhs)"). Quindi, proprio perché questo genere di cose è interessante, volevo provare a scrivere un "Applica F generico" ai primi elementi di questa coppia " funtore. Ho scritto il seguito, ma a g ++ non piace. Ottengo:

errore: tipo / valore non corrispondente all'argomento 2 nell'elenco dei parametri del modello per 'template struct Pair1stFunc2' errore: previsto un tipo, ottenuto "meno"

#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

template <class P, class F>
struct Pair1stFunc2
{
    typename F::result_type operator()(P &lhs, P &rhs) const
    { return F(lhs.first, rhs.first); }

    typename F::result_type operator()(const P &lhs, const P &rhs) const
    { return F(lhs.first, rhs.first); }
};

typedef std::pair<int,int> MyPair;
typedef std::vector<MyPair> MyPairList;

MyPairList pairs;

void foo(void)
{
    std::sort(pairs.begin(),
              pairs.end(),
              Pair1stFunc2<MyPair, std::less>());
}

Qualcuno può far luce su ciò che sto facendo di sbagliato qui? So che questo è un esempio leggermente artificiale, ma mi piacerebbe sapere cosa sta succedendo, anche solo per migliorare il mio STL-fu.

È stato utile?

Soluzione

Devi specializzare std :: less con il tipo di confronto che stai usando.

Pair1stFunc2<MyPair, std::less<int> >()

farà il trucco. All'interno del tuo operatore () dovrai anche istanziare un oggetto del tipo di confronto, poiché non puoi semplicemente chiamare direttamente la classe. Per esempio. cambi il tempo

return F(lhs.first, rhs.first);

a

F func;
return func(lhs.first, rhs.first);

Potresti anche spostare la specializzazione nel functor, come suggerisce un'altra risposta.

Altri suggerimenti

Per espandere la risposta di dirkgently, ecco un esempio di cosa potrebbe funzionare come previsto:

template <typename T, template <typename> class F>
struct Pair1stFunc2
{
    template <typename P>
    typename F<T>::result_type operator()(P &lhs, P &rhs) const
    { F<T> f; return f(lhs.first, rhs.first); }

    template <typename P>
    typename F<T>::result_type operator()(const P &lhs, const P &rhs) const
    { F<T> f; return f(lhs.first, rhs.first); }
};

void foo(void)
{
    std::sort(pairs.begin(),
              pairs.end(),
              Pair1stFunc2<int, std::less>());
}

Nota che funziona, ma potrebbe non essere esattamente quello che avevi in ??mente.

Nota che std :: less è esso stesso un modello e non specifichi il parametro modello modello quando lo chiami con funzione della funzione foo () ! Qui less è un tipo incompleto e quindi il problema.

Simile a indesiderato. Ma non è necessario utilizzare i modelli di modello.

#include <algorithm>
#include <functional>
#include <memory>
#include <vector>

typedef std::pair<int,int> MyPair;
typedef std::vector<MyPair> MyPairList;
MyPairList pairs;


// Same as original.
template <typename T,typename F>
struct Pair1stFunc2
{
    template <typename P>
    typename F::result_type operator()(P &lhs, P &rhs) const
    { F f;  // Just need to create an anstance of the functor to use.
      return f(lhs.first, rhs.first); }

    template <typename P>
    typename F::result_type operator()(const P &lhs, const P &rhs) const
    { F f;  // Just need to create an anstance of the functor to use.
      return f(lhs.first, rhs.first); }
};


void foo(void)
{
    std::sort(pairs.begin(),
              pairs.end(),
              Pair1stFunc2<int, std::less<int> >()); // initialize the version of less
}

La soluzione più semplice sarebbe quella di affermare ciò che vuoi come argomento, una funzione con una firma adatta:

template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... }

In questo caso, il passaggio di un modello di funzione come secondo argomento comporterà la risoluzione del sovraccarico su di esso con P, P come tipi di argomento. Questo funziona perché si sposta la risoluzione di sovraccarico da struct Pair1stFunc2 :: operator ()

Volete anche la possibilità di passare un functor , ma questi devono essere passati come argomento di tipo template e quindi creati all'interno di operator ():

typename F::result_type operator()(const P &lhs, const P &rhs) const
{ return F()(lhs.first, rhs.first); }

Qui, F è il tipo di funzione e F () un'istanza di quel funzione.

Il terzo caso è già stato trattato in precedenza, il modello di funzione. std :: less è un tale modello. In tal caso, è necessario un argomento modello modello.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top