2013-02-11 2 views
3

정수에 여러 bool을 저장하기위한 템플릿 클래스를 작성했습니다. 은 지금 설정하고 각 부울을 얻는 것은배열이 아닌 요소에 대한 첨자 연산자 오버플로

bool isBitSet(int index) 
    { 
     return static_cast<bool>((block_ >> index) % 2) 
    } 

    void setBitOn(int index) 
    { 
     block_ |= 1 << index; 
    } 

나는 우리가 직접 비트에 대한 참조를 반환 할 수 있기 때문에 값을 얻기 위해 일 것이다 다음,하지만 어떻게 작업을 설정하는 것이라고 생각 명시 적 기능을 수행 ?

const bool operator [] (int index) const 
    { 
     return static_cast<bool>((block_ >> index) % 2); 
    } 
+0

다른 모든 하위 사용 연산자는 kaboom으로 이동합니다! –

+0

일반적인 유형의 작업에 과부하를주는 것은 좋지 않습니다. – Rapptz

+2

왜'std :: bitset'을 사용하는 대신에 사용하지 않으시겠습니까? – chris

답변

5

같은 표준 라이브러리에 std::vector<bool>std::bitset에서 이루어집니다. reference에 명시된 바와 같이 std::vector<bool>은 벡터의 요소로 작동하도록 오버로드 된 연산자가있는 프록시 클래스를 반환합니다.

당신도 그렇게 할 수 있습니다.

template <class Allocator> 
class vector<bool, Allocator> { 
    // ... 
    public: 
    class reference { 
     friend class vector; 
     reference(); 
     public: 
     ~reference(); 
     operator bool() const; 
     reference& operator=(bool x); 
     reference& operator=(const reference&); 
     void flip(); 
    }; 
    // ... 
}; 

당신이 당신의 실제 데이터 블록과 마스크에 멤버 포인터를 저장해야이 클래스를 구현하려면 다음 사용자에게 친숙한 예를 들어

공용 인터페이스에 다시 reference보고,이 같은 것입니다 와 함께 작동합니다.

실제 예를 들어, g ++ 헤더에서 bits/stl_bvector.h 파일에 std::vector<bool>::_Bit_reference이라는 이라는 멤버 클래스가 있는지 찾아보십시오.


는 예를 이용하여 OP를 명확히하기 위해 :

이의 당신이 320 bools를 포함하는 클래스가 있다고 가정 해 봅시다. 다음과 같이 쓸 수 있습니다 :

class boolcontainer { 
    uint32_t data[10]; 
public: 
    //default ctor. to initialize the elements with zeros 
    boolcontainer() { for (int i = 0; i < 10; ++i) { data[i] = 0; } } 
} 

연산자 []를 추가하고 싶습니다. const를 추가하는 것은 쉽습니다 :

class boolcontainer { 
    uint32_t data[10]; 
public: 
    bool operator[](int i) const { return data[i/32] & (1 << (i%32)); } 
} 

당신이 훨씬 더 필요로하는 비 const 하나를 갖기. 먼저 값에 대한 참조를 나타내는 클래스를 만들어야합니다. 값이 저장되는 곳을 가리키는 어떤 종류의 포인터가 있어야하며 (이 경우) 하나의 구체적인 비트를 지정하기 위해 비트 마스크가 필요합니다. 당신이 bool에와 연산자, 일부 사업자를 추가, 즉 변환이 필요 & = 부울로이 문제를 처리 할 수 ​​있어야합니다 : 부울 &로 위의 구조체이 동작하는 것을

class reference { 
    uint32_t *dataptr; 
    uint32_t mask; 
public: 
    //constructor just initializing members 
    reference(uint32_t *dataptr_, uint32_t mask_) : dataptr(dataptr_), mask(mask_) {} 

    //conversion to bool 
    operator bool() const { 
    //just like in the getter, but the bitmask is stored now locally 
    return *dataptr & mask; 
    } 

    //sets one single bit represented by mask to b 
    reference& operator=(bool b) { 
    if (b) { 
     *dataptr |= mask; 
    } else { 
     *dataptr &= ~mask; 
    } 
    return *this; 
    } 

    //TODO copy ctor., operator==, operator< 
}; 

주 - 읽는이를 읽고 값을 포인터와 마스크로 표현 된 데이터 포인트에서 가져오고, 비슷하게 표현 된 위치에서 비트를 덮어 씁니다. 나는 또한 멤버들을 초기화하는 생성자를 썼다. 지금

class boolcontainer { 
    uint32_t data[10]; 
public: 

    boolcontainer() { for (int i = 0; i < 10; ++i) { data[i] = 0; } } 

    class reference { 
    ... //see above 
    } 

    //keep the const version for efficiency 
    bool operator[](int i) const { return data[i/32] & (1 << (i%32)); } 

    //non-const version returns our reference object. 
    reference operator[](int i) { return reference(&data[i/32], 1 << (i%32)); } 
}; 

그리고 (인쇄 첫 번째 40 값)을 테스트하는 몇 가지 코드 :

지금 당신이 필요로하는 모든 당신의 boolcontainer의 연산자 []은 위 클래스의 객체를 반환해야한다는 것입니다

#include <iostream> 
#include "boolcontainer.h" 

void printboolcontainer(const boolcontainer &bc) 
{ 
    //note that this is the constant version 
    for (int i = 0; i < 40; ++i) { 
     std::cout << bc[i]; 
    } 
    std::cout << std::endl; 
} 

int main() 
{ 
    boolcontainer bc; 
    printboolcontainer(bc); 
    bc[0] = true; 
    bc[3] = true; 
    bc[39] = true; 
    printboolcontainer(bc); 
} 
+0

나는 그것을보고 있었고 나는'_Bit_reference operator [] (ptrdiff_t __i) const {return * (* this + __i);}'까지 갔지만 그 일을 이해하도록 도와 줄 수 있습니까? –

+0

명확히하기 위해 예제를 추가했습니다. STL은 템플리트와 밑줄이 그어진 식별자로도 마찬가지입니다. – Csq

+0

고마워요! 나는 주로 따라갈 수 있었다. 그러나 문제는 여전히있다. 왜'reference operator = (int i)'에서'* this'를 돌려 주나요? –