2013-11-17 4 views
0

Массивы битмаски действительно популярны, часто времена они утомительно писать, и они делают код менее читаемым, я хотел бы, чтобы генерировать их с constexpr, вот моя попыткаC++ 11 - bad_alloc на constexpr

#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); 
} 

Я использовал std::move, безымянные объекты и constexpr этот код компилируется нормально с

g++-4.8 -O3 -std=c++11 -pthread -Werror -Wall -Wextra 

но он не во время выполнения из-за bad_alloc, и я могу видеть, что мой «маленький» приложение распределения много пространства.

Возможно, ошибка огромная, и я не вижу ее, но почему это не работает?

Почему мое приложение выполняет распределение во время выполнения? Не предполагается ли вычислять все во время компиляции? Я ожидал, что это может быть неудачно во время компиляции не во время выполнения.

ответ

2

std::bad_alloc обычно означает, что он не может выделить больше памяти. Изменение кода к следующему покажет вам, почему:

for (T count = lower; count < upper; count += step) { 
    std::cout << "count:" << count << "\n"; 
    std::cout << "upper:" << upper << "\n"; 
}; 

Это печатает следующий на первом цикле, когда я тестировал:

count:0 
upper:4294967295 

Другими словами, у вас есть длинный путь, прежде чем count < upper не работает, и цикл for останавливается, тем более, что вы добавляете только 256 каждый раз.

Кроме того, для функций constexpr, подлежащих оценке во время компиляции, есть определенные conditions it has to fullfil. Например, its return type must be LiteralType, и ваша функция возвращает std::vector, также, exactly one return statement that contains only literal values, constexpr variables and functions. и у вас есть составной оператор. Поэтому ваша функция не может быть оценена во время компиляции.

Также обратите внимание, что если вы не заполняете эти условия, квалификатор constexpr игнорируется, хотя если вы включите -pedantic, он должен дать вам лучшую диагностику.

+1

Возможно, стоит отметить, что если он выполняет функцию без шаблона, его код вообще не будет компилироваться. – sbabbi

+0

Infact Я фокусировался на диапазоне для моего типа 'uint32_t', и я забыл, что вектор тоже нуждается в памяти ...; поэтому, если я хотел бы разбить компиляцию, если игнорировать 'constexpr'-классификатор, что лучший способ сделать это? – user2485710

+0

@ user2485710: [Это невозможно] (http://stackoverflow.com/questions/14309245/single-expression-helper-for-compile-time-enforced-constexpr-function-evaluation). –

Смежные вопросы