Frage

Ich habe über mit functors in C ++ zu spielen. Insbesondere habe ich einen Vektor von Paaren bekam ich durch das erste Element des Paares sortieren möchten. Ich begann einen ganz speziellen Funktors Schreiben (das heißt so etwas wie "Bool MyLessThan (MyPair & lhs, MyPair & rhs)"). Dann, gerade weil diese Art von Sachen interessant ist, wollte ich eine generische, um versuchen zu schreiben „F Nehmen, um die ersten Elemente dieses Paares“ Funktor. Ich schrieb die folgenden, aber g ++ mag es nicht. Erhalte ich:

Fehler: Typ / Wert Mismatch bei Argumente 2 in Vorlage Parameterliste für 'template struct Pair1stFunc2' Fehler: eine Art erwartet, bekam ‚weniger‘

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

Kann jemand Aufschluss über was ich falsch hier? Ich weiß, das als leicht artifizielles Beispiel ist, aber ich würde gerne wissen, was los ist, wenn nur mein STL-fu zu verbessern.

War es hilfreich?

Lösung

Sie müssen std :: spezialisieren weniger mit dem Vergleichstyp Sie verwenden.

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

wird den Trick. In Ihrem eigenen Operator () Sie müssen auch ein Objekt des Vergleichstypen instanziiert, da Sie die Klasse direkt nicht nur anrufen können. Z.B. Änderung

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

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

Sie können auch die Spezialisierung in den Funktors bewegen, wie eine andere Antwort vermuten lässt.

Andere Tipps

dirkgently Antwort erweitern auf, hier ist ein Beispiel dafür, was funktionieren kann, wie Sie beabsichtigen:

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>());
}

Beachten Sie, dass es funktioniert, aber es ist vielleicht nicht genau das, was Sie im Sinn hatte.

Beachten Sie, dass std::less selbst eine Vorlage und Sie nicht über die Template-Template-Parameter angeben, wenn Sie es aus mit foo() Funktion der sort nennen! Hier less ist ein unvollständiger Typ und daher das Problem.

Ähnlich Unwesen. Aber Sie brauchen keine Vorlage Vorlagen.

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

Die einfachste Lösung wäre es, zu sagen, was Sie als Argument wollen, eine Funktion mit einer geeigneten Signatur:

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

In diesem Fall wird eine Funktionsschablone als das zweite Argument übergibt verursacht Überladungsauflösung auf sich mit P, P als Argumenttypen durchgeführt werden. Dies funktioniert, weil Sie die Überladungsauflösung aus struct Pair1stFunc2::operator()

bewegen

Sie möchten auch die Möglichkeit, in einem der vorbei Funktors , aber die brauchen als Vorlagentyp Argument übergeben werden und dann innerhalb Betreiber erstellt wurden ():

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

Hier F ist die Funktor Art und F () eine Instanz dieses Funktor.

Der dritte Fall ist bereits früher abgedeckt, die Funktors Vorlage. std :: weniger ist so eine Vorlage. In diesem Fall müssen Sie eine Vorlage Template-Argument.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top