Функция constexpr не вычисляет значение во время компиляции

Я хочу сравнить метапрограммирование и использование constexpr в C++0x. тогда я пишу FIB-функцию в обеих моделях. когда я использую модель метапрограммирования, ответ распечатывается очень быстро, потому что он рассчитывается во время компиляции. но когда я использую функцию constexpr, она вычисляет значение во время выполнения, а не во время компиляции. Я использую g++( gcc) 4.8 . Может ли какое-нибудь тело помочь мне?

#include <iostream>
using namespace std;
#define NUM 42

template <unsigned int N>
struct Fibonacci {
    enum { value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value };
};

template <>
struct Fibonacci<1> {
    enum { value = 1 };
};

template <>
struct Fibonacci<0> {
    enum { value = 1 };
};

constexpr unsigned int fib(unsigned int n)
{
    return (n > 1 ? fib(n-1) + fib(n-2) : 1 );
}

int main()
{

    cout << "Meta_fib(NUM)      : " << Fibonacci<NUM>::value << endl; // compile time :)
    cout << "Constexpr_fib(NUM) : " << fib(NUM) << endl;        // run time :-?
    return 0;
}

4 ответа

Решение

Я считаю, что причина в том, что constexpr не гарантируется выполнение во время компиляции. Чтобы обеспечить оценку во время компиляции, вы должны назначить ее псевдониму во время компиляции. Подобно,

enum {i = fib(NUM)};

По крайней мере, с помощью gcc вы можете получить значение constexpr, вычисляемое во время компиляции, сделав его статической переменной:

static const unsigned fibNUM = fib(NUM);

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

constexpr не гарантируется, что будет оцениваться во время компиляции. Это означает, что компилятор может выбирать, выполнять ли оценку во время компиляции или во время выполнения. Вы можете попытаться присвоить его постоянной времени компиляции и проверить, как это...

const long i = fib(NUM);// here i should be initialized at the time of 
                        // declaration
cout << "Meta_fib(NUM)      : " << Fibonacci<NUM>::value << endl; 
cout << "Constexpr_fib(NUM) : " << i << endl;

Простой тест, чтобы увидеть, если ваш constexpr на самом деле делается во время компиляции, чтобы использовать std::array:

#include <array>

std::array<int, Fibonacci<5>::value> arr;
std::array<int, fib(5)> arr2;

GCC не имеет претензий.

Смотрите этот комментарий Бьярна Страуструпа:

... в соответствии со стандартом функция constexpr может оцениваться во время компиляции или во время выполнения, если только она не используется в качестве константного выражения, и в этом случае она должна оцениваться во время компиляции. Чтобы гарантировать оценку во время компиляции, мы должны либо использовать ее там, где требуется постоянное выражение (например, в качестве границы массива или в качестве метки регистра), либо использовать ее для инициализации constexpr. Я надеюсь, что ни один уважающий себя компилятор не упустит возможность оптимизации сделать то, что я первоначально сказал: "Функция constexpr вычисляется во время компиляции, если все ее аргументы являются константными выражениями".

Другие вопросы по тегам