C ++, возвращает константную и неконстантную ссылку на элемент std :: set - PullRequest
2 голосов
/ 25 января 2012

Существует класс A, содержащий два перегруженных метода getItems ();

typedef std::vector <int> TItems;

template <typename T>
class A 
{
private:
    T a;
    TItems items;

public:
    A(){}
    A ( const T a_, const TItems & items_) : a(a_) , items (items_) {}
    bool operator () ( const A <T> &aa ) {return a < aa.a;}
    TItems const & getItems() const {return items}
    TItems & getItems() {return items}
};

и набор объектов A

template <typename T>
struct TSet {typedef std::set <A <T> > Type;};

Я хотел бы вернуть константную ссылку / ссылку наTItems, но работает только второй метод

int main ()
{
TSet <double> ::Type t;
TSet <double> ::Type::iterator it = t.begin();
t.insert (A <double>( 5, TItems(10,10)));

const TItems *items = &(it->getItems()); //OK
TItems *items = &(it->getItems()); //Error  
}

Error   1   error C2440: 'initializing' : cannot convert from 'const TItems *' to 'TItems *

Является ли причиной того, что непостоянные ссылки позволяют изменять объекты A, вызывая потенциальную перестановку в наборе?Но элементы набора расположены не по A.items, а по.

Есть ли способ, как изменить A.items с помощью непостоянной ссылки?

Ответы [ 3 ]

2 голосов
/ 25 января 2012

Является ли причиной того, что непостоянные ссылки позволяют изменять объекты A, вызывая потенциальную перестановку в наборе?

Точно. Элементы std::set (и ключи BTW std::map) являются неизменяемыми, структура будет давать только элементы с константной квалификацией. Таким образом, у вас есть опция

  • измените свою структуру на std::map и укажите a в качестве ключа и items в качестве данных
  • если вы абсолютно уверены, что не нарушите порядок, манипулируя items, вы можете const_cast (или объявить items mutable, если вас это устраивает).
1 голос
/ 25 января 2012

Если вам разрешено изменять элементы набора, вы можете нарушить инварианты структуры, реализующей набор (например, сбалансированное дерево поиска). Элементы наборов должны быть неизменными. Поэтому вы должны удалить элемент и заменить его новым, если хотите изменить элемент. В частности, вы не можете ожидать неконстантную ссылку через итератор на set (если вы можете изменить ее, вы можете нарушить порядок). .

0 голосов
/ 25 января 2012

Вы не можете изменять объекты, хранящиеся в std :: set, потому что это нарушит установленные инварианты.Вместо этого вы можете удалить объект из набора, затем изменить его и вставить снова.

Другая возможность - использовать вместо него std :: map.Ключ карты не может быть изменен, но значение может.

...