Следующее плохо:
vector<const int> vec;
Проблема в том, что тип шаблона должен быть назначаемым. Следующий код компилирует [EDIT: в Visual Studio 2010], демонстрируя проблему с вышеуказанным:
vector<const int> vec;
vec.push_back(6);
vec[0] += 4;
С более сложными типами это может быть серьезной проблемой.
Мой первый вопрос: есть ли причина для такого поведения? Мне кажется, что возможно создать const-контейнеры, которые запрещают вышеупомянутые, и неконстантные контейнеры, которые позволяют это.
Во-вторых, есть ли способ сделать контейнеры, которые работают таким образом?
В-третьих, что на самом деле происходит здесь (с типом пользователя)? Я понимаю, что это неопределенное поведение, но как STL вообще компилирует это?
Причина std::vector<T const>
не допускается, что объект в векторе может потребоваться перестановка при вставке в другое место, чем в начале. Теперь член std::vector<T>::push_back(T const& v)
концептуально эквивалентно (опуская параметр шаблона распределителя, так как он не имеет значения для этого обсуждения)
template <typename T>
void std::vector<T>::push_back(T const& v) {
this->insert(this->end(), v);
}
кажется, как это реализовано в некоторых реализациях. Теперь эта операция требует, в общем, чтобы некоторые объекты могли перемещаться и, таким образом, T
Аргумент должен быть назначаемым. Кажется, что стандартная библиотека, поставляемая с MSVC ++, не делегирует операцию, а выполняет всю необходимую обработку, то есть изменяет размер массива и перемещает объекты соответствующим образом, когда заканчивается пространство, в push_back()
, Не совсем понятно, какие требования предъявляются к типу T
быть в состоянии использовать push_back()
,
В принципе, контейнер, поддерживающий оба T const
и insert()
Операция в середине была бы возможна, однако: ничто не требует, чтобы внутреннее хранилище было T
скорее, чем typename std::remove_const<T>::type
выставляя T&
в интерфейсе. Надо быть немного осторожнее с const
-версия операций типа operator[]()
потому что просто используя T const&
в качестве типа возврата при T
это какой-то тип S const
приведет к типу S const const
, В C ++ 2003 это было бы ошибкой, в C ++ 2011 я думаю, что const
просто рухнули. Чтобы быть в безопасности, вы можете использовать typename std::add_const<T>::type&
,
Других решений пока нет …