Я могу записать функторы с помощью частной вложенной структуры?

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

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

Идея здесь - это fooList может быть индексирован также key1 или key2 из структуры Foo. Я пытаюсь записать функторы для передачи std::find_if таким образом, я могу искать объекты в fooList каждым ключом. Но я не могу заставить их компилировать потому что Foo является частным в классе (это не часть интерфейса C). Есть ли способ сделать это без представления 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;
    }
};
5
задан Michael Kristofik 22 March 2010 в 16:03
поделиться

6 ответов

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

Заголовок:

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
ответ дан 14 December 2019 в 13:32
поделиться

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

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

0
ответ дан 14 December 2019 в 13:32
поделиться

Да. Сделайте функтор другим членом 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;
}
2
ответ дан 14 December 2019 в 13:32
поделиться

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

1
ответ дан 14 December 2019 в 13:32
поделиться

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

1
ответ дан 14 December 2019 в 13:32
поделиться

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

0
ответ дан 14 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: