2010-03-22 5 views
5

diese Klasse Gegeben:Kann ich Funktoren mit einer privaten verschachtelten Struktur schreiben?

class C 
{ 
    private: 
     struct Foo 
     { 
      int key1, key2, value; 
     }; 
     std::vector<Foo> fooList; 
}; 

Die Idee dabei ist, dass fooList entweder durch key1 oder key2 der Struktur Foo indiziert werden können. Ich versuche Funktoren zu schreiben, die ich an std::find_if weiterleiten kann, damit ich mit jeder Taste Gegenstände in fooList nachschlagen kann. Aber ich kann sie nicht kompilieren, weil Foo innerhalb der Klasse privat ist (es ist nicht Teil der C-Schnittstelle). Gibt es eine Möglichkeit, dies zu tun, ohne Foo dem Rest der Welt auszusetzen?

Hier ist ein Beispiel-Code, der nicht kompiliert, weil Foo in meiner Klasse ist privat:

struct MatchKey1 : public std::unary_function<Foo, bool> 
{ 
    int key; 
    MatchKey1(int k) : key(k) {} 
    bool operator()(const Foo& elem) const 
    { 
     return key == elem.key1; 
    } 
}; 

Antwort

2

ich so etwas tun würde.

Rubrik:

class C 
{ 
private: 
    struct Foo 
    { 
     int index; 
     Bar bar; 
    }; 

    // Predicates used to find Notification instances. 
    struct EqualIndex; 
    struct EqualBar; 

    std::vector<Foo> fooList; 
}; 

Quelle:

// Predicate for finding a Foo instance by index. 
struct C::EqualIndex : std::unary_function<C::Foo, bool> 
{ 
    EqualIndex(int index) : index(index) { } 
    bool operator()(const C::Foo& foo) const { return foo.index == index; } 
    const int index; 
}; 

// Predicate for finding a Foo instance by Bar. 
struct C::EqualBar : std::unary_function<C::Foo, bool> 
{ 
    EqualBar(const Bar& bar) : bar(bar) { } 
    bool operator()(const C::Foo& foo) const { return foo.bar == bar; } 
    const Bar& bar; 
}; 

Verbrauch:

// Find the element containing the Bar instance someBar. 
std::vector<Foo>::iterator it = std::find_if(fooList.begin(), 
              fooList.end(), 
              EqualBar(someBar)); 

if (it != fooList.end()) 
{ 
    // Found it. 
} 

Sort of ...

+0

+1, vergaß ich einfach weiter zu erklären, die Funktoren zu verschachtelten Strukturen als auch. Ich habe auch einen Tippfehler (copy-and-paste-o?) Für Sie behoben. –

+0

@Kristo: Kopieren und Einfügen-o? du wette-o! ;) –

1

Sie könnten den Funktors einen Freund von C machen.

2

Ja. Mache den Funktor zu einem weiteren Mitglied von C und verkapsele std::find_if hinter einer Methode von C.

Es folgt ein Beispiel:

#include "stdafx.h" 
#include <vector> 
#include <cassert> 
#include <algorithm> 
#include <iostream> 

class C 
{ 
    private: 
     struct Foo 
     { 
      int key1, key2, value; 
     }; 

     std::vector<Foo> fooList; 

    struct Finder 
    { 
    private: 
     int key1, key2; 

    public: 
     Finder(int k1, int k2) 
     { 
     key1 = k1; 
     key2 = k2; 
     } 

     bool operator()(Foo const& foo) const 
     { 
     return foo.key1 == key1 || foo.key2 == key2; 
     } 
    }; 

public: 
    C() 
    { 
    Foo foo1, foo2; 
    foo1.key1 = 5; 
    foo1.key2 = 6; 
    foo1.value = 1; 
    foo2.key1 = 7; 
    foo2.key2 = 8; 
    foo2.value = 10; 

    fooList.insert(fooList.begin(), foo1); 
    fooList.insert(fooList.begin(), foo2); 
    } 

    int Find(int key1, int key2) 
    { 
    return std::find_if(fooList.begin(), fooList.end(), Finder(key1, key2))->value; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    C c; 

    std::cout << c.Find(5, 3) << std::endl; 
    std::cout << c.Find(3, 6) << std::endl; 
    std::cout << c.Find(7, 3) << std::endl; 
    std::cout << c.Find(3, 8) << std::endl; 

    return 0; 
} 
1

Die Syntax ist ziemlich barock, aber ich konnte drehen fooList in zu einem boost::multi_index_container indexiert auf key1 und key2.

+0

+1, für all die Male schlug ich multi_index vor und wurde nie upvoted;) – pmr

0

Wenn Sie Ihre Struktur nicht in der Kopfzeile benötigen, können Sie auch unbenannte Namespaces in Ihrer Implementierungsdatei verwenden, um die Definitionen und Deklarationen lokal zur Kompilierungseinheit zu machen (wobei static die C-ähnliche Alternative static ist).

Dies führt zu einem saubereren Header, der nicht von Implementierungsdetails verdeckt wird.

+0

Ich denke, 'Foo' muss noch in der Kopfzeile deklariert werden, weil' fooList' davon abhängt. –

+0

@Kristo: Sicher, aber die Frage war über den Funktor nicht die Struktur selbst.Die eigentliche Frage ist, ob die Struktur Foo wirklich nur ein Implementierungsdetail ist oder ob es außerhalb Ihrer Klasse bereitgestellt werden sollte. – pmr

0

Ich könnte die Pimpl Idiom verwenden, um den privaten Abschnitt C in einer anderen Klasse zu verbergen. Da alles in sicher öffentlich sein kann, sollte ich in der Lage sein, mit Foo dort zu tun, was ich will.

Verwandte Themen