Ошибка: не удается получить доступ к закрытому члену, объявленному в классе boost::signals2::scoped_connection?

class Whatever
{
public:
    virtual ~Whatever();

protected:
    Whatever();
    virtual void SomeMethod();
    void OnEventOccurred(int x);

    std::vector<boost::signals2::scoped_connection> boostSignalConnections_;
}

// .cpp

Whatever::SomeMethod()
{
    ...
    boostSignalConnections_.push_back(
        anObject->AddEventOccurredObserver(
            std::bind(&Whatever::OnEventOccurred,
                      this, std::placeholders::_1)));
    ...
}

(Обратите внимание, что AddEventOccurredObserver просто делегирует boost::signals2::connect() и возвращает boost::signals2::connection)

Я получаю следующую ошибку. Трудно интерпретировать ошибки шаблона, но похоже, что ошибка возникает при объявлении члена std::vector<boost::signals2::scoped_connection> boostSignalConnections_;

...\vc\include\xmemory(202): error C2248:  
    'boost::signals2::scoped_connection::scoped_connection' :
    cannot access private member declared in class 'boost::signals2::scoped_connection'
...\boost_1_47\boost\signals2\connection.hpp(234) : see declaration of
'boost::signals2::scoped_connection::scoped_connection'
...\boost_1_47\boost\signals2\connection.hpp(210) :
    see declaration of 'boost::signals2::scoped_connection'
...\vc\include\xmemory(201) : while compiling class template member function
'void std::allocator<_Ty>::construct(boost::signals2::scoped_connection *,_Ty &&)'
with
[
    _Ty=boost::signals2::scoped_connection
]

Я искал и думаю, что это может быть связано с тем, что scoped_connection не может быть скопирован? Я не уверен. Причина, по которой я использую scoped_connection, связана с этим вопросом SO: Обрабатывать подключение/отключение многих сигналов/слотов с помощью boost::signals2

Обновить

К вашему сведению, когда я меняю scoped_connection на connection, работает: std::vector<boost::signals2::connection> boostSignalConnections_;. Вся причина, по которой я использую scoped_connection, заключается в том, что они автоматически отключают соединение при разрушении, тогда как я считаю, что connection этого не делает. Однако я могу просто перебирать коллекцию и вручную отключать каждую из них.


person User    schedule 04.05.2012    source источник
comment
Вы правы, проблема в том, что конструктор копирования является закрытым. Поскольку vector необходимо копировать элементы в случае перераспределения (например, из-за расширения), это проблема. Однако у меня нет лучшего решения для вас, поэтому я оставлю это другим, чтобы фактически ответить на неявный вопрос, что мне делать вместо этого? Мой первый, наивный ответ состоял бы в том, чтобы сохранить вектор указателей/ссылок на соединения, выделенные в куче, но это, очевидно, в значительной степени устраняет полезность части scoped уравнения.   -  person tmpearce    schedule 04.05.2012


Ответы (1)


boost::signals2::scoped_connection не является копируемым, а в C++03 std::vector<T> требует, чтобы T был как копируемым, так и копируемо-назначаемым (это требование ослаблено в C++11, где некопируемый тип подходит, если он перемещаемый). вместо).

Наивным решением было бы вместо этого сделать boostSignalConnections_ std::vector<scoped_connection*>, но это создает проблемы со временем жизни объекта и безопасностью исключений, которые не стоят затраченных усилий. Вместо этого, в зависимости от того, насколько свеж ваш компилятор, я бы рекомендовал следующее:

  • C++03: используйте boost::ptr_vector<scoped_connection>, который будет хранить указатели для вас (разрешая некопируемые типы ), но дает вам семантику значений и устраняет вышеупомянутые проблемы времени жизни объекта и безопасности исключений.
  • C++11: Вышеприведенный вариант по-прежнему допустим, но более идиоматичным подходом было бы использование std::vector<std::unique_ptr<scoped_connection>>.

При этом зачем использовать scoped_connection, если вы не хотите, чтобы ваш объект был лексически ограничен?

person ildjarn    schedule 04.05.2012
comment
Хороший вопрос, но, как я уже упоминал, я следовал примеру в вопросе, связанном с моим вопросом (хотя здесь используется карта, так что, может быть, это другое?) Мне показалось необычным использовать объект с областью видимости в контейнере, но я не такой знаком с ними. - person User; 04.05.2012
comment
@User : верно, к значениям ассоциативного контейнера предъявляются более слабые требования, чем к значениям контейнера последовательности и ключам ассоциативного контейнера. - person ildjarn; 04.05.2012
comment
@ildjarn Когда вы говорите, что boost::ptr_vector<> поддерживает время жизни объекта, означает ли это, что он развертывает smart_pointers на сервере для достижения того же? Если да, то какой? - person CinCout; 24.04.2018
comment
@CinCout: я не смотрел на реализацию, но, насколько мне известно, это непубличная деталь реализации; вероятно, это было бы бесполезно вне контекста библиотеки. Лучше думать о boost::ptr_vector<> как об умном контейнере, который устраняет необходимость в умном указателе. ;-] - person ildjarn; 24.04.2018
comment
@ildjarn Значит, гарантируется, что управление памятью осуществляется контейнером? Или есть какие-то (экстра)обычные исключения из того же? - person CinCout; 24.04.2018
comment
@CinCout: Это гарантировано - в конце концов, это единственная причина существования библиотеки. TBH Я не уверен, какой у вас вопрос, который не рассматривается на первой странице документов библиотеки... - person ildjarn; 24.04.2018