Ответ 1
Мотивация для этого расширения, которая обнаруживается соответствующей программой и, следовательно, несоответствие, заключается в том, чтобы сделать vector<bool>
более похожим на vector<char>
на ссылки (const и в противном случае).
Введение
С 1998 года vector<bool>
высмеивается как "не совсем контейнер". LWG 96, одна из первых проблем с LWG, запустила дискуссию. Сегодня, спустя 17 лет, vector<bool>
остается практически неизменным.
В этой статье приводятся некоторые конкретные примеры того, как поведение vector<bool>
отличается от любого другого экземпляра vector
, тем самым ущемляя общий код. Однако в одной и той же статье подробно рассматриваются очень хорошие характеристики производительности vector<bool>
, если они правильно реализованы.
Сводка: vector<bool>
не является плохим контейнером. Это действительно полезно. У него просто плохое имя.
Вернуться к const_reference
Как было показано выше, и подробно описано здесь, что плохо о vector<bool>
заключается в том, что он ведет себя по-разному в родовом коде, чем другие vector
конкретизации. Вот конкретный пример:
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]); // Fires!
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
В стандартной спецификации указано, что объявленный знак // Fires!
будет запускаться, но только тогда, когда test
запускается с vector<bool>
. При запуске с vector<char>
(или любым vector
кроме bool
, когда назначается соответствующий нестандартный T
), тест проходит.
Реализация libС++ была направлена на минимизацию негативных последствий того, что vector<bool>
ведет себя по-разному в общем коде. Для достижения этой цели нужно сделать vector<T>::const_reference
прокси-ссылку, точно так же, как указанную vector<T>::reference
, за исключением того, что вы не можете ее назначить. То есть, в libС++, vector<T>::const_reference
по существу является указателем на бит внутри vector
, а не на копию этого бита.
В libС++ выше test
проходит как для vector<char>
, так и vector<bool>
.
Какую стоимость?
Недостатком является то, что это расширение обнаруживается, как показано в вопросе. Однако очень мало программ действительно заботятся о точном типе этого псевдонима, и больше программ заботятся о поведении.
Какова мотивация этого несоответствия?
Чтобы дать более качественное поведение клиента libС++ в общем коде и, возможно, после достаточного полевого тестирования, предложите это расширение будущему стандарту С++ для улучшения всей отрасли С++.
Такое предложение может быть представлено в виде нового контейнера (например, bit_vector
), который имеет тот же API, что и сегодня vector<bool>
, но с несколькими обновлениями, такими как const_reference
, обсуждаемые здесь. Затем следует отсрочка (и возможное удаление) специализации vector<bool>
. bitset
может также использовать небольшую модернизацию в этом отделе, например. add const_reference
и набор итераторов.
То есть, задним числом bitset
соответствует vector<bool>
(который должен быть переименован в bit_vector
- или что-то еще), поскольку array
соответствует vector
. И аналогия должна быть достоверной, независимо от того, говорим ли мы о bool
как value_type
из vector
и array
.
Существует несколько примеров функций С++ 11 и С++ 14, которые начинаются как расширения в libС++. Именно так развиваются стандарты. Фактическое продемонстрированное поле позитивный оказывает сильное влияние. Стандартные люди - консервативная группа, когда дело доходит до изменения существующих спецификаций (как и должно быть). Угадав, даже если вы уверены, что правильно догадываетесь, это рискованная стратегия для разработки международно признанного стандарта.