Frage

Wenn ich ein Objekt wie folgt aus:

struct Bar {
    std::string const& property();
};

Ich kann es so einen Multi-Index Container erstellen:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

Aber wenn ich eine Klasse wie folgt:

struct Foo {
   Bar const& bar();
};

Wie kann ich einen Index für .bar().property() für einen Container von Foo Objekte konstruieren?

Normalerweise würde ich Nest ruft boost::bind, aber ich kann nicht herausfinden, wie es im Rahmen eines Multi-Index-Container arbeitet zu machen.

War es hilfreich?

Lösung

Ich glaube, Sie brauchen ein Prädikat-Objekt zu erstellen, die Foo zwei Instanzen von Foo und dessen Betreiber () nimmt aufrufen :: bar () auf beiden Instanzen.

So etwas wie

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

und verwenden Sie dann

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

Schauen Sie sich Multiindex Bestellen Indizes Referenz

Andere Tipps

Anstatt einen benutzerdefinierten Komparator bereitstellt, können Sie schreiben eine benutzerdefinierte Schlüsselentnehmer :

struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

Siehe Erweiterte Funktionen von Boost.Multiindex Schlüsselentnehmer

So viel wie Ich mag lambda mit einfachen Dinge zu tun, kann dies schnell degeneriert:)

In Ihrem Fall, da es ein bisschen komplizierter ist, würde ich entweder auf einer freien Funktion oder ein Prädikat Komparator verlassen.

Das Prädikat hat den Vorteil, Typen deutlicher zu definieren, so dass es in der Regel einfacher ist es tatsächlich zu bringen.

Auch zum besseren Lesbarkeit willen, ich in der Regel meine Indizes typedef, was ergibt:

namespace mi = boost::multi_index;

struct FooComparator
{
  bool operator()(Foo const& lhs, Foo const& rhs) const
  {
    return lhs.bar().property() < rhs.bar().property();
  }
};

typedef mi::ordered_unique <
          mi::tag<tag_prop>,
          mi::identity<Foo>,
          FooComparator
        > foo_bar_index_t;

typedef boost::multi_index_container <
          Foo,
          mi::indexed_by < 
            foo_bar_index_t,
            // ... other indexes
          >
        > foo_container_t;

Das Prädikat Ansatz erfordert mehr Standardcode, sondern erlaubt es schön aus der Indexdefinition die Vergleichslogik zu trennen, die sich von der Container-Definition getrennt ist.

Klare Trennung erleichtert die Struktur auf einen Blick zu sehen.

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