3

if i write,

int a=10,b=12;
int sub = b-a;

std::bitset<8*sub> bits(bitMask);

it is giving me an error saying

error C2975: '_Bits' : invalid template argument for 'std::bitset', expected compile-time constant expression

how to over come this error, i want to initialize bitset at run time, is it possible? or there any other way to do this?

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Naruto
  • 9,476
  • 37
  • 118
  • 201

4 Answers4

3

Template parameters must be compile-time constants. Think of a template as a code generator: The code has to be generated before you start compiling. You cannot use templates "at runtime"!

const unsigned int size = 10;
std::bitset<size> b;  // fine, the compiler knows what "size is"

unsigned int n; cin >> n;
std::bitset<n> c;     // doesn't make sense!

As a first step you should say const as much as possible in your code; it's possible that you actually do have compile-time constants but aren't declaring them as such.

If you really need a data structure with dynamic size, you need to use something else (e.g. a vector of unsigned chars along with a bitwise accessor function).


Here's a very simple implementation of a bit set as a vector of chars. I'm not wrapping this in a class, you can do that if that's needed:

std::vector<unsigned char> data;

bool getBit(size_t n, const std::vector<unsigned char> & data)
{
  if (data.size() * CHAR_BIT) <= n) return 0;

  return data[n / CHAR_BIT] & (1U << (n % CHAR_BIT));
}

void setBit(size_t n, std::vector<unsigned char> & data)
{
  if (data.size() * CHAR_BIT) <= n) data.resize(n / CHAR_BIT + 1, 0);

  data[n / CHAR_BIT] |= (1U << (n % CHAR_BIT));
}

// Exercise for the reader
void clrBit(size_t n, std::vector<unsigned char> & data);
void tglBit(size_t n, std::vector<unsigned char> & data);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • i tried adding const, its not taking at all.. same error what i have posted is appearing – Naruto Aug 03 '11 at 09:35
  • Well, post some real code. Your above example should work if you make all the numbers constant. – Kerrek SB Aug 03 '11 at 09:36
  • const int sub =Count-ErrorByte+1; std::bitset<8*sub> bits(bitMask); – Naruto Aug 03 '11 at 09:37
  • the above code in my comment doesn't work :( – Naruto Aug 03 '11 at 09:37
  • *Everything* has to be constant, including `Count` and `ErrorByte`! – Kerrek SB Aug 03 '11 at 09:38
  • i did, " const int byte_count = ByteCount; const int error_byte = ErrorByte; const int sub = byte_count-error_byte+1; std::bitset<8*sub> bits(bitMask);" – Naruto Aug 03 '11 at 09:41
  • still above code fails... could you please tell me why? – Naruto Aug 03 '11 at 09:41
  • Hey, it works only if i assign constant number, eg const int byte_count= 20 but it does't work if it is const int byte_count = ByteCount. – Naruto Aug 03 '11 at 09:46
  • No no, **everything** has to be const, recursively :-) This includes `ErrorByte` and `ByteCount`. Basically, you cannot do it *because your data isn't determined at compile time*. Think about it: Code generation. Code has to be generated at compile time. Consider one of the alternatives. – Kerrek SB Aug 03 '11 at 09:46
  • @KerrekSB let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/2089/discussion-between-lll-and-kerrek-sb) – Naruto Aug 03 '11 at 09:47
  • Hi Kerrek, is there any alternative to bitset to handle these sort of run time situations. please let me know if u have any idea – Naruto Aug 03 '11 at 09:51
  • I already did: use a dynamic structure. Me, I'd go with `std::vector`, and then access the `n`th bit as the `n%CHAR_BIT`th bit of `v[n/CHAR_BIT]`. – Kerrek SB Aug 03 '11 at 10:01
  • could you please post your answer.. it will be very helpful.. i need to enumerate binary data like array based on the number of bytes. – Naruto Aug 03 '11 at 10:44
  • I wrote a bit of a skeleton code for querying and switching on bits. You can make up the code for switching off and toggling from that I guess. – Kerrek SB Aug 03 '11 at 10:52
3

The Standard's anwser to your question is to use std::vector<bool>, which is a bit set which can dynamically accomodate its size.

Please keep in mind that std::vector<bool> is a specialization of std::vector which is allowed to store bits in the most memory efficient way. (This is why it sucks: it doesn't behave like std::vector<T> for other Ts. If you want a real std::vector of bool, you can't.)

The interface is kept identical to std::bitset (this also sucks, because generic code using vector will break hell if instantiated with bool), so your existing code shouldn't break.

The std::vector<bool> specialization will be deprecated in the next standard. If you are already using C++0x, the correct alternative is std::dynamic_bitset. If you are stuck with the current C++ standard, then std::vector<bool> is what you want.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
1

You can use boost::dynamic_bitset if you want a... dynamic bitset (I know, crazy, right?).

boost::dynamic_bitset<> bits(8 * sub, bitMask);
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
0

In your case, you can just stick a const on there so it's a constexpr:

const int a=10,b=12;
const int sub = b-a;

std::bitset<8*sub> bits;

(From comment) You can't initialize a bitset at runtime; that's why it's a template argument, or compile-time constant

An alternative would be to use a std::vector of bools which has been wrapped in a class with some custom access functions

Seb Holzapfel
  • 3,793
  • 1
  • 19
  • 22