Альтернатива вектору<bool>
Как (надеюсь) мы все знаем, vector<bool>
полностью сломан и не может рассматриваться как массив переменного тока. Каков наилучший способ получить эту функциональность? До сих пор я думал о следующих идеях:
- Использовать
vector<char>
вместо или - Используйте класс-оболочку и
vector<bool_wrapper>
Как вы, ребята, справляетесь с этой проблемой? Мне нужна функциональность c_array().
В качестве дополнительного вопроса, если мне не нужен метод c_array(), каков наилучший способ решения этой проблемы, если мне нужен произвольный доступ? Должен ли я использовать deque или что-то еще?
Редактировать:
- Мне нужен динамический размер.
- Для тех, кто не знает,
vector<bool>
специализируется так, что каждый бул занимает 1 бит. Таким образом, вы не можете преобразовать его в массив в стиле c. - Я думаю, что "обертка" является немного неправильным. Я думал что-то вроде этого:
Конечно, тогда я должен прочитать в my_bool из-за возможных проблем с выравниванием:(
struct my_bool
{
bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
8 ответов
Использование std::deque
если вам не нужен массив, да.
В противном случае используйте альтернативу vector
это не специализируется на bool
Например, в Boost Container.
Это интересная проблема.
Если вам нужно то, что было бы std::vector, если бы оно не было специализированным, то, возможно, что-то подобное отлично подойдет для вашего случая:
#include <vector>
#include <iostream>
#include <algorithm>
class Bool
{
public:
Bool(): m_value(){}
Bool( bool value ) : m_value(value){}
operator bool() const { return m_value;}
// the following operators are to allow bool* b = &v[0]; (v is a vector here).
bool* operator& () { return &m_value; }
const bool * const operator& () const { return &m_value; }
private:
bool m_value;
};
int main()
{
std::vector<Bool> working_solution(10, false);
working_solution[5] = true;
working_solution[7] = true;
for( int i = 0; i < working_solution.size(); ++i )
{
std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
}
std::sort( working_solution.begin(), working_solution.end());
std::cout<< "--- SORTED! ---" << std::endl;
for( int i = 0; i < working_solution.size(); ++i )
{
bool* b = &working_solution[i]; // this works!
std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
}
std::cin.get();
return 0;
}
Я попробовал это с VC9, и, кажется, работает нормально. Идея класса Bool состоит в том, чтобы моделировать тип bool, предоставляя такое же поведение и размер (но не один и тот же тип). Почти вся работа выполняется оператором bool и конструкторами копирования по умолчанию. Я добавил сортировку, чтобы убедиться, что она реагирует так, как предполагалось при использовании алгоритмов.
Не уверен, что это подойдет для всех случаев. Если это подходит для ваших нужд, это будет меньше работы, чем переписать вектороподобный класс...
Зависит от ваших потребностей. Я бы пошел на любой std::vector<unsigned char>
, Написание оболочки может быть хорошо, если вы используете только часть функций, иначе это станет кошмаром.
Как вы, ребята, справляетесь с этой проблемой? Мне нужна функциональность c_array().
boost::container::vector<bool>
:
Специализация vector < bool > была довольно проблематичной, и было несколько неудачных попыток осудить или удалить ее из стандарта.
Boost.Container
не реализует его, так как существует превосходное решение Boost.DynamicBitset....
Так что boost:: container:: vector:: iterator возвращает реальные bool-ссылки и работает как полностью совместимый контейнер. Если вам нужна оптимизированная для памяти версия функциональных возможностей boost:: container:: vector < bool >, используйте Boost.DynamicBitset.
Попробуйте использовать вектор
Вектор
Если вы действительно хотите чистую семантику, мне также нравится предложение создать свой собственный логический класс - выглядит как bool, действует как bool, но обманывает специализацию шаблонов.
Кроме того, добро пожаловать в клуб людей, которые хотят, чтобы специализация vector
Эта проблема уже обсуждалась на comp.lang.C++. Модерируется. Предлагаемые решения:
- ваш собственный распределитель (на основе
std::allocator
) и собственная векторная специализация; - использование
std::deque
(как раньше было рекомендовано в одной из книг С. Майерса) - но это не по вашим требованиям; - сделать POD
bool
обертка; - использовать что-то (
char
/int
/ etc) с тем же размером, что иbool
вместоbool
;
Также рано я увидел предложение для стандартного комитета - ввести макрос (что-то вроде STD_VECTOR_BOOL_SPECIAL
) запретить эту специализацию - но AFAIK это предложение не было реализовано в реализациях stl и не было одобрено.
Кажется, у вашей проблемы нет способов сделать это красиво... Может быть, в C++0x.
Самый простой ответ - это использование vector<struct sb>
где sb
является struct {boolean b};
, Тогда вы можете сказать push_back({true})
, Это выглядит неплохо.
Мой предпочтительный обходной путь - это vector
enum с ограниченным доступом, который имеет базовый тип bool
, Это довольно близко к vector<bool>
мы бы имели, если бы комитет не специализировал это.
enum class switch_status : bool { ON, OFF };
static_assert( sizeof( switch_status ) == 1 );
::std::vector<switch_status> switches( 20, switch_status::ON );
static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches.back() ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches[ 0 ] ), switch_status &> );
Вы будете иметь свое собственное мнение о мудрости принятия бросков в / из bool
:
enum class switch_status : bool { OFF = false, ON = true };
static_assert( static_cast< bool >( switch_status::ON ) == true );
static_assert( static_cast< bool >( switch_status::OFF ) == false );
static_assert( static_cast< switch_status >( true ) == switch_status::ON );
static_assert( static_cast< switch_status >( false ) == switch_status::OFF );