C++11 - bad_alloc on a constexpr
Question
Arrays with bitmasks are really popular, often times they are tedious to write and they make the code less readable, I would like to generate them with a constexpr
, here is my try
#include <iostream>
#include <cstdint>
#include <vector>
#include <utility>
typedef uint32_t myT;
template <typename T>
constexpr std::vector<T> vecFarm(T &&lower, T &&upper, T &&step) {
// std::cout << lower << " " << upper << " " << step << "\n";
std::vector<T> v;
if (lower < upper) {
for (T count = lower; count < upper; count += step) {
v.push_back(count);
};
}
return (v);
}
int main() {
std::vector<myT> k(std::move(vecFarm(myT(0), ~(myT(0)), myT(256)))); //why
// this doesn't work ?
// std::vector<myT> k(std::move(vecFarm(myT(0), ((~(myT(0))) >> 16), myT(256))));
// but this one works
// let's see what we got
for (const auto &j : k) {
std::cout << j << " ";
}
std::cout << "\n";
return (0);
}
I have used std::move
, unnamed objects and a constexpr
, this code compiles fine with
g++-4.8 -O3 -std=c++11 -pthread -Werror -Wall -Wextra
but it fails at runtime because of a bad_alloc
, and I can see my "small" application allocating a lot of space .
Maybe the error is huge and I can't see it, but why this doesn't work ?
Why my application does the allocation at run-time ? Isn't supposed to compute everything at compile-time ? I was expecting this to maybe fail at compile-time not at run-time.
Solution
std::bad_alloc
usually means it cannot allocate any more memory. Changing your code to the following will show you why:
for (T count = lower; count < upper; count += step) {
std::cout << "count:" << count << "\n";
std::cout << "upper:" << upper << "\n";
};
This prints the following on the first loop when I tested it:
count:0
upper:4294967295
In other words, you have a long way to go before count < upper
fails and the for loop stops, especially since you are adding only 256
each time.
Also, in order for constexpr
functions to be evaluated at compile time, there are certain conditions it has to fullfil. For example, its return type must be LiteralType
, and your function returns std::vector
, also, exactly one return statement that contains only literal values, constexpr variables and functions.
and you have a compound statement. Therefore, your function cannot be evaluated at compile time.
Also, note that if you do not fullfill these conditions, the constexpr
qualifier is ignored, although if you turn on -pedantic
it should give you better diagnostics.