указатели — Как получить неконстантный доступ к объекту, удерживаемому контейнером, когда контейнер является константным в переполнении стека

У меня есть связь между двумя классами и некоторым дополнительным функциональным кодом, показанным в следующем примере. MiddleMan класс содержит пару контейнеров указателей на DataObject экземпляры классов. Я хочу обеспечить доступ только для чтения к объектам данных в одном контейнере, в то же время разрешая доступ на запись к контейнерам данных в другом. Пользователи MiddleMan никогда не должны иметь возможность изменять сами контейнеры ( ptr_vector члены).

Я думаю, что продвижение const происходит с DataObject указатели при доступе через MiddleMan постоянная функция-член. Как я могу избежать этого? В моих объектных отношениях, MiddleMan логически не владеет DataObject экземпляров. Таким образом, я не хочу DataObject экземпляры const-защищены.

Я использовал boost::ptr_vector контейнер, как я понимаю, контейнеры STL могут быть более проблематичными для такого рода вещей. Не решил мою проблему, хотя.
Я счастлив использовать const_cast в MiddleMan, но я не вижу как.

// const correctness access through middleman example
// g++ -I/Developer/boost  ptr_container_ex.cc
#include <boost/ptr_container/ptr_vector.hpp>

struct DataObject
{
DataObject(size_t n) : _data(new float[n]) {}
~DataObject() {delete _data;}
float * dataNonConst() { return _data; }
const float * dataConst() const { return _data; }
float * _data;
};struct MiddleMan
{

typedef boost::ptr_vector<DataObject> containerVec_t;

const containerVec_t & inputVars() const { return _inputVars; }
const containerVec_t & outputVars() const { return _outputVars; }

void addInputVar(  DataObject * in  ) { _inputVars.push_back( in ); }
void addOutputVar( DataObject * out ) { _outputVars.push_back( out ); }

containerVec_t _inputVars, _outputVars;

};

// just an example that the DataObject instances are managed externally
DataObject g_dataInstances[] = {DataObject(1), DataObject(2), DataObject(3)};

MiddleMan theMiddleMan;int main()
{
theMiddleMan.addInputVar( &g_dataInstances[0]);  // this is just setup
theMiddleMan.addOutputVar( &g_dataInstances[1]);

const MiddleMan & mmRef = theMiddleMan; // I actually only have a const ref to work with

// read data example
const MiddleMan::containerVec_t & inputs = mmRef.inputVars();
float read = inputs[0].dataConst()[0];

// write data example
const MiddleMan::containerVec_t & outputs = mmRef.outputVars();
float * data_ptr = outputs[0].dataNonConst(); // COMPILER ERROR HERE:

return 0;
}

Я получаю вывод компилятора:

ptr_container_ex.cc: In function ‘int main()’:
ptr_container_ex.cc:49: error: passing ‘const DataContainer’ as ‘this’ argument of ‘float* DataContainer::dataNonConst()’ discards qualifiers

0

Решение

Вам нужно исключить модификаторы const в каждом месте, к которому у вас нет доступа к const:

containerVec_t & outputVars() { return _outputVars; } //Change definition in MiddleMan class

MiddleMan::containerVec_t & outputs = theMiddleMan.outputVars(); //Change reference type
float * data_ptr = outputs[0].dataNonConst(); //No compiler error here
1

Другие решения

Один рабочий сценарий использует const_cast в доступе к outputVars. Я не могу вернуть ссылку на весь контейнер, но могу получить нужную мне функциональность, возвращая начальный и конечный итераторы.

// const correctness access through middleman example
// g++ -I/Developer/boost  ptr_container_ex.cc
#include <boost/ptr_container/ptr_vector.hpp>

struct DataObject
{
DataObject(size_t n) : _data(new float[n]) {}
~DataObject() {delete _data;}
float * dataNonConst() { return _data; }
const float * dataConst() const { return _data; }
float * _data;
};struct MiddleMan
{
typedef boost::ptr_vector<DataObject> containerVec_t;

containerVec_t::iterator outputVarsBegin() const { return const_cast<containerVec_t&>(_outputVars).begin(); }
containerVec_t::iterator outputVarsEnd() const { return const_cast<containerVec_t&>(_outputVars).end(); }

const containerVec_t & inputVars() const { return _inputVars; }

void addInputVar(  DataObject * in  ) { _inputVars.push_back( in ); }
void addOutputVar( DataObject * out ) { _outputVars.push_back( out ); }

containerVec_t _inputVars, _outputVars;

};

// just an example that the DataObject instances are managed externally
DataObject g_dataInstances[] = {DataObject(1), DataObject(2), DataObject(3)};

MiddleMan theMiddleMan;int main()
{
theMiddleMan.addInputVar( &g_dataInstances[0]);  // this is just setup
theMiddleMan.addOutputVar( &g_dataInstances[1]);

const MiddleMan & mmRef = theMiddleMan; // I actually only have a const ref to work with

// read data example
const MiddleMan::containerVec_t & inputs = mmRef.inputVars();
float read = inputs[0].dataConst()[0];

// write data example
float * data_ptr2 = mmRef.outputVarsBegin()->dataNonConst(); // WORKS

return 0;
}
-1