Почему libc++'s vector: const reference не bool?
Раздел 23.3.7 Класс vector<bool> [вектор.bool], пункт 1 гласит:
template <class Allocator> class vector<bool, Allocator> {
public:
// types:
typedef bool const_reference;
...
однако эта программа не компилируется при использовании libc++:
#include <vector>
#include <type_traits>
int
main()
{
static_assert(std::is_same<std::vector<bool>::const_reference, bool>{}, "?");
}
кроме того, я отмечаю, что стандарт C++ был согласован в этой спецификации вплоть до C++98. И я также отмечаю, что libc++ последовательно не следовал этой спецификации с момента первого введения libc++.
какова мотивация этого несоответствия?
1 ответов
мотивация для этого расширения, которое обнаруживается соответствующей программой и, следовательно, не соответствует, состоит в том, чтобы сделать vector<bool> ведите себя больше как vector<char> в отношении ссылок (const и в противном случае).
введение
С 1998 года, vector<bool> был высмеян как " не совсем контейнер."LWG 96, один из самых первых вопросов РГПВ, запустил дебаты. Сегодня, 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);
}
в стандартной спецификации говорится, что assert отмечен // Fires! вызовет, но только когда test С vector<bool>. При запуске с vector<char> (или vector кроме того bool когда соответствующий не-default T is назначено), тест проходит.
реализация libc++ стремилась свести к минимуму негативные последствия наличия vector<bool> вести себя по-разному в общем коде. Одна вещь, которую он сделал, чтобы достичь этого, - это сделать vector<T>::const_reference a прокси-ссылка, как указано 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 это vector<bool> (который следует переименовать в bit_vector -- или что угодно), как array это vector. И аналогия должна быть верной независимо от того, говорим мы о bool как value_type of vector и array.
существует несколько примеров функций C++11 и C++14, которые начинались как расширения в libc++. Вот как развиваются стандарты. Фактический продемонстрировал положительное полевой опыт оказывает сильное влияние. Люди стандартов-консервативная группа, когда дело доходит до изменения существующих спецификаций (как и должно быть). Угадывание, даже если вы уверены, что угадываете правильно, является рискованной стратегией для разработки международно признанного стандарта.