vector <bool>의 대안


92

(희망적으로) 우리 모두가 알고 있듯이 vector<bool>완전히 깨져서 C 배열로 취급 될 수 없습니다. 이 기능을 얻는 가장 좋은 방법은 무엇입니까? 지금까지 내가 생각한 아이디어는 다음과 같습니다.

  • vector<char>대신 사용 하거나
  • 래퍼 클래스를 사용하고 vector<bool_wrapper>

이 문제를 어떻게 처리합니까? c_array()기능이 필요합니다 .

부수적 인 질문으로, c_array()방법이 필요하지 않은 경우 임의 액세스가 필요한 경우이 문제에 접근하는 가장 좋은 방법은 무엇입니까? 데크 나 다른 것을 사용해야합니까?

편집하다:

  • 동적 크기 조정이 필요합니다.
  • 모르는 분들을 위해, vector<bool>각각 bool1 비트를 취 하도록 특화되어 있습니다. 따라서 C 스타일 배열로 변환 할 수 없습니다.
  • 나는 "래퍼"가 약간 잘못된 이름이라고 생각한다. 나는 다음과 같이 생각하고 있었다.

물론 my_bool정렬 문제로 인해를 읽어야 합니다.

struct my_bool
{
    bool the_bool;
};
vector<my_bool> haha_i_tricked_you;

2
C 스타일 배열을 사용하지 않을 이유가 있습니까?
kquinn

rlbond, 동적 크기가 필요합니까?
Johannes Schaub-litb

16
Ok I 'll bite-왜 벡터가 ""완전히 깨졌다 "고 생각합니까?
Andrew Grant


4
흥미롭게도 vector<bool>다른 스레드가 벡터의 다른 요소를 동시에 안전하게 수정할 수 있기를 기대했기 때문에 코드에서 데이터 경합 버그가 발생했습니다. 를 사용하여 해결되었습니다 deque<bool>.
Andres Riofrio 2013 년

답변:



21

흥미로운 문제입니다.

전문화되지 않았다면 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* 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 연산자와 기본 복사 생성자에 의해 수행됩니다. 알고리즘을 사용할 때 가정 한대로 반응하도록 정렬을 추가했습니다.

모든 경우에 적합할지 확실하지 않습니다. 당신의 필요에 맞다면 벡터와 같은 클래스를 다시 작성하는 것보다 덜 작업이 될 것입니다.


"부울 * 연산자를 추가 할 수 있습니다. & () {return & m_value;}"-오류. ISO는 " sizeof(bool)이 될 필요는 없다 1"
예브게니 Panasyuk을

2
나는 단순히 operator bool() constoperator bool&(). 이렇게하면 할당 등을 지원하므로 단순한 bool의 동작을 더 잘 반영합니다. v[0] = true;이 변경 사항에 대한 문제를 실제로 볼 수없는 경우 편집 할 수 있습니까?
Agentlien 2014 년

19

귀하의 필요에 따라 다릅니다. 나는 둘 중 하나를 갈 것입니다 std::vector<unsigned char>. 래퍼를 작성하는 것은 기능의 일부만 사용하면 괜찮을 수 있습니다. 그렇지 않으면 악몽이 될 것입니다.


unsigned charuint8_t구현에서 지원되지 않을 수 있지만 항상 단일 바이트 입니다. uint_fast8_t의도는 그것이 단일 바이트가 아닌 캐릭터의 취소 할 경우 비록 작동 할 수 있지만, 당신은뿐만 아니라 사용할 수 있습니다 std::byte다음
가브리엘 Ravier을

13

이 문제를 어떻게 처리합니까? c_array () 기능이 필요합니다.

boost::container::vector<bool>:

vector < bool > 전문화는 문제가 많았으며 표준에서 제거하거나 제거하려는 시도가 여러 번 실패했습니다. Boost.Container우수한 Boost.DynamicBitset 이 있기 때문에 구현하지 않습니다. 솔루션 .

...

따라서 boost :: container :: vector :: iterator 는 실제 bool 참조를 반환하고 완전히 호환되는 컨테이너로 작동합니다. boost :: container :: vector < bool > 기능 의 메모리 최적화 버전이 필요한 경우 Boost.DynamicBitset을 사용 하십시오 .


6

vector <int> 사용을 고려하십시오. 컴파일과 타입 검사를 지나면 bool과 int는 모두 기계어 일뿐입니다 (편집 : 분명히 이것은 항상 사실은 아니지만 많은 PC 아키텍처에서 사실입니다). 경고없이 변환하려는 경우 "bool foo = !! bar"를 사용하여 0을 거짓으로, 0이 아닌 값을 참으로 변환합니다.

벡터 <char> 또는 이와 유사한 것은 문자가 기계어 크기보다 작기 때문에 일부 상황에서 (매우 작은) 속도에 걸릴 가능성이 있지만 공간을 덜 사용합니다. 이것이 bool이 char 대신 int를 사용하여 구현되는 주된 이유라고 생각합니다.

당신이 정말로 깨끗한 의미를 원한다면, 나는 또한 자신의 부울 클래스를 만드는 제안을 좋아합니다. 부울처럼 보이고 부울처럼 작동하지만 템플릿 전문화를 속입니다.

또한, vector <bool> 전문화를 C ++ 표준에서 제외하고 싶은 사람들의 클럽에 오신 것을 환영합니다 (bit_vector를 대체 할 수 있음). 모든 멋진 아이들이 어울리는 곳입니다. :).


4

이 문제는 이미 comp.lang.c ++. moderated에서 논의 되었습니다. 제안 된 솔루션 :

  • 자신의 할당 자 (기반 std::allocator ) 및 자체 벡터 전문화
  • 사용하다 std::deque (S. Mayers 책 중 하나에서 일찍 권장 됨)-그러나 이것은 귀하의 요구 사항이 아닙니다.
  • POD 만들기 bool 포장지 ;
  • 대신 같은 크기의 무언가 ( char// intetc)를 bool사용하십시오 bool.

또한 초기에 표준위원회에 대한 제안을 보았습니다. STD_VECTOR_BOOL_SPECIAL 에이 전문화를 허용하지 않는 )를 보았지만 AFAIK이 제안은 stl 구현에서 구현되지 않았고 승인되지 않았습니다.

당신의 문제는 이것을 멋지게 할 방법이없는 것 같습니다 ... 아마도 C ++ 0x에서.


3

가장 간단한 대답은 vector<struct sb>어디에서 사용 하는 것 sb입니다 struct {boolean b};. 그런 다음 말할 수 있습니다 push_back({true}). 좋아 보인다.


2

내가 선호하는 해결 방법은 vector기본 유형이 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 );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.