Question

Compte tenu de cette classe:

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

L'idée ici est que fooList peut être indexé par l'une ou key1 key2 de la struct Foo. Je suis en train d'écrire foncteurs passer à std::find_if je peux regarder par chaque touche articles dans fooList. Mais je ne peux pas les amener à compilent parce Foo est privé au sein de la classe (il ne fait pas partie de l'interface C). Est-il possible de le faire sans exposer Foo au reste du monde?

Voici un exemple de code qui ne compile pas parce que Foo est privé au sein de ma classe:

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;
    }
};
Était-ce utile?

La solution

Je ferais quelque chose comme ça.

En-tête:

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

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

    std::vector<Foo> fooList;
};

Source:

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

Utilisation:

// 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.
}

Trier des ...

Autres conseils

Oui. Faire foncteur un autre membre de C et std::find_if derrière une encapsulation méthode de C.

Voici un exemple:

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

Vous pouvez faire foncteur un ami de C.

La syntaxe est assez baroque, mais je pouvais fooList en boost::multi_index_container indexé sur key1 et key2.

Si vous n'avez pas besoin de votre struct dans votre tête vous pouvez également utiliser les espaces de noms sans nom dans votre dossier de mise en œuvre pour que les définitions et les déclarations unité locale à la compilation (avec statique étant la static autre type C).

Ceci vous laisse avec un en-tête de nettoyage qui n'est pas obscurci par des détails de mise en œuvre.

Je pourrais utiliser Pimpl Idiom pour cacher la partie privée de C dans une autre classe. Puisque tout en CImpl peut en toute sécurité publique, je serais capable de faire tout ce que je veux avec Foo là.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top