constexpr и std :: cout работают над функцией, но не в лямбде - PullRequest
8 голосов
/ 12 июня 2019

Почему constexpr не работает с std::cout, но работает с printf?

#include <iostream>
constexpr void f() { std::cout << ""; } //error
constexpr void g() { printf(""); } //ok

И почему std::cout работает с лямбдами constexpr?

#include <iostream>
int main () {
    auto h = []() constexpr { std::cout << ""; }; //ok
}

Ответы [ 2 ]

11 голосов
/ 12 июня 2019

Технически, он не работает ни с одним из них.

С [dcl.constexr] :

Для функции constexpr или конструктора constexprэто не является ни значением по умолчанию, ни шаблоном, если не существует значений аргумента, так что вызов функции или конструктора может быть оцененным подвыражением выражения основной константы или, для конструктора, инициализатором константы для некоторого объекта ([basic.start.static]), программа некорректна, диагностика не требуется .

f() и g() никогда не являются константными выражениями (ни std::cout << x, ни printf() являются функциями constexpr), поэтому объявление constexpr неверно сформировано.Но компилятор не требует для диагностики этого (в этом случае это может быть легко, но в общем случае ... не так уж и много).Вы видите, что ваш компилятор смог диагностировать одну проблему, но не другую.

Но они оба не правы.

7 голосов
/ 12 июня 2019

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

constexpr int a = f(), 0; // fails
constexpr int b = g(), 0; // fails

constexpr функции, которые никогда не производят постоянное выражение, плохо сформированы;Диагностика не требуется.Это означает, что компиляторы делают все возможное, чтобы проверить, так ли это, но ваша программа в любом случае уже имеет ошибку.Похоже, gcc не видит, что printf не является константным выражением. лязг ошибок при определении .

...