Могу ли я написать функторы, используя частную вложенную структуру? - PullRequest
5 голосов
/ 22 марта 2010

Учитывая этот класс:

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

Идея состоит в том, что fooList может быть проиндексирован либо key1, либо key2 структуры Foo. Я пытаюсь написать функторы для передачи на std::find_if, чтобы я мог искать элементы в fooList по каждой клавише. Но я не могу заставить их скомпилировать, потому что Foo является приватным внутри класса (это не часть интерфейса Си). Есть ли способ сделать это, не подвергая Foo остальному миру?

Вот пример кода, который не будет компилироваться, потому что Foo является закрытым в моем классе:

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

Ответы [ 6 ]

2 голосов
/ 22 марта 2010

Я бы сделал что-то подобное.

Заголовок:

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

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

    std::vector<Foo> fooList;
};

Источник:

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

Использование:

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

Вроде ...

2 голосов
/ 22 марта 2010

Да. Сделайте функтор другим членом C и инкапсулируйте std::find_if после метода C.

Ниже приведен пример:

#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 голос
/ 22 марта 2010

Синтаксис довольно барочный, но я мог бы превратить fooList в boost::multi_index_container, индексированный на key1 и key2.

1 голос
/ 22 марта 2010

Вы можете сделать функтора другом C.

0 голосов
/ 22 марта 2010

Я мог бы использовать Pimpl Idiom , чтобы скрыть частный раздел C внутри другого класса. Так как все в CImpl может безопасно быть общедоступным, я должен иметь возможность делать все, что захочу, с Foo там.

0 голосов
/ 22 марта 2010

Если вам не нужна ваша структура внутри заголовка, вы также можете использовать безымянные пространства имен в файле реализации, чтобы сделать определения и объявления локальными для модуля компиляции (при этом static является C-подобной альтернативой static).

Это дает вам более чистый заголовок, который не скрыт деталями реализации.

...