Подтвердить что ты не робот

Использование функции constexpr перед определением не выполняется

У меня проблемы с constexpr. В книге С++ Primer показана строка кода:

  constexpr int sz = size(); // only size() is a constexpr function
                             // this code is right

Однако книга не дает конкретного примера. Поэтому я сам пробую следующий код:

#include <iostream>
constexpr int fun();
int main()
{
    constexpr int f = fun();
    std::cout << f << std::endl;
}
constexpr int fun()
{
    return 3;
}

Но мой компилятор сказал, что fun() - undefined.

Если я изменяю constexpr на const, он работает хорошо, и если я изменю свой код, чтобы определить функцию constexpr перед использованием:

#include <iostream>
constexpr int fun()
{
    return 3;
}
int main()
{
    constexpr int f = fun();
    std::cout << f << std::endl;
}

Он также хорошо работает. Может кто-нибудь сказать мне, почему?

4b9b3361

Ответ 1

Функция A constexpr НЕ ДОЛЖНА быть определена до ее первого использования, однако результат любого вызова, сделанного до определения, не является постоянным выражением.

Источник: С++ Стандартная черновик n4296, раздел 5.20:

условное выражение e является выражением основной константы, если оценка e, следуя правилам абстрактной машины, не будет оценивать одно из следующих выражений:

  • this, за исключением функции constexpr или конструктора constexpr, который оценивается как часть e;
  • вызов функции, отличной от конструктора constexpr для литерального класса, функции constexpr или неявного вызова тривиального деструктора [Примечание: разрешение перегрузки применяется как обычный - конец примечания];
  • вызов функции undefined constexpr или конструктора undefined constexpr;
  • ...

из проекта 3485 (раздел 5.19):

Условное выражение является выражением основной константы, если оно не включает одно из следующего в качестве потенциально оцениваемого подвыражения, но не рассматриваются подвыражения логических И, логических ИЛИ и условных операций, которые не оцениваются [Примечание: перегруженный оператор вызывает функцию. - конец примечания]:

  • this [Примечание: при оценке константного выражения подстановка подстановки функций заменяет каждое вхождение this в функции-члене constexpr указателем на объект класса. - конечная нота];
  • вызов функции, отличной от конструктора constexpr для функции literal или constexpr [Примечание: разрешение перегрузки применяется как обычно - примечание конца);
  • вызов функции undefined constexpr или конструктора undefined constexpr
  • ...

Пример int x2 = s. t(); в n2235 действительно стал действительным из-за изменений, внесенных до стандартизации. Однако constexpr int x2 = s. t(); остается ошибкой.

Ответ 2

Функция постоянного выражения должна быть определена до ее первого использования. Смотрите paper, конец раздела 4.1.