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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top