Почему 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++. Вот как развиваются стандарты. Фактический продемонстрировал положительное полевой опыт оказывает сильное влияние. Люди стандартов-консервативная группа, когда дело доходит до изменения существующих спецификаций (как и должно быть). Угадывание, даже если вы уверены, что угадываете правильно, является рискованной стратегией для разработки международно признанного стандарта.