Мотивация для этого расширения, которое может быть обнаружено соответствующей программой и, следовательно, не соответствует требованиям, состоит в том, чтобы заставить 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]);
}
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), тест проходит.
Реализация libc ++ стремилась свести к минимуму негативные последствия vector<bool>различного поведения в общем коде. Единственное , что он сделал , чтобы добиться этого , чтобы сделать vector<T>::const_referenceна прокси-ссылки , так же , как указано vector<T>::reference, за исключением того, что вы не можете назначить через него. То есть в libc ++ это, vector<T>::const_referenceпо сути, указатель на бит внутри vector, а не копия этого бита.
В libc ++ вышеуказанное testподходит как для, так vector<char>и для vector<bool>.
Какой ценой?
Обратной стороной является то, что это расширение обнаружимо, как показано в вопросе. Однако очень немногие программы действительно заботятся о точном типе этого псевдонима, и больше программ заботятся о его поведении.
Какова мотивация этого несоответствия?
Чтобы улучшить поведение клиента libc ++ в общем коде и, возможно, после достаточного полевого тестирования, предложите это расширение для будущего стандарта C ++ для улучшения всей индустрии C ++.
Такое предложение могло бы появиться в форме нового контейнера (например bit_vector), который будет иметь почти такой же API, как сегодняшний vector<bool>, но с некоторыми обновлениями, такими как const_referenceобсуждаемые здесь. За этим следует прекращение поддержки (и возможное удаление) vector<bool>специализации. bitsetтакже можно было бы использовать небольшое обновление в этом отделе, например, добавить const_referenceи набор итераторов.
То есть в ретроспективе bitsetэто to vector<bool>(которое следует переименовать в bit_vector- или что-то еще), as arrayis to vector. И аналогия должна верны ли или нет , мы говорим о том, boolкак value_typeиз vectorи array.
Есть несколько примеров функций C ++ 11 и C ++ 14, которые начинались как расширения в libc ++. Так развиваются стандарты. Фактический продемонстрированный положительный полевой опыт оказывает сильное влияние. Специалисты по стандартам - консервативная группа, когда дело доходит до изменения существующих спецификаций (как и должно быть). Гадание, даже если вы уверены, что угадываете правильно, - рискованная стратегия для развития международно признанного стандарта.
vector<bool>на более первоклассную основу?