Почему constexpr работает с шаблонами?

Рассмотрим следующий код:

template<typename T>
constexpr inline T fma(T a, T b, T c)
{
    return a * b + c;
}

Это прекрасно компилируется. Но почему это? Теоретически функции constexpr могут вызывать только другие функции constexpr. Однако нет гарантии, что операторы будут функциями constexpr. Например, скажем, у меня есть какой-то тип со следующим интерфейсом:

 class someType
 {
    someType operator + (const someType &rhs);
    someType operator * (const someType &rhs);
 };

Операторы + и * не constexpr. Если я напишу следующий код:

fma(someType(), someType(), someType());

Он не должен компилироваться, потому что функция constexpr вызывает функции, не являющиеся constexpr. Но компилируется отлично. Почему это?

Я использую компилятор MinGW G ++ с параметром -std = c ++ 0x.


person Publius    schedule 09.09.2012    source источник
comment
В качестве примера, где явно очевидно, что нельзя все оптимизировать, он компилируется с GCC 4.7.1, когда вводятся три аргумента, и выводится результат: ideone.com/aBRPU   -  person chris    schedule 09.09.2012
comment
попробуйте это: constexpr someType dummy = fma(someType(), someType(), someType());;)   -  person mfontanini    schedule 09.09.2012
comment
Ох, я только что обнаружил в стандарте, что constexpr функции неявно встроены, если это сэкономит вам место.   -  person chris    schedule 09.09.2012
comment
mfontanininininini: Это не работает, но на самом деле не отвечает на мой первоначальный вопрос.   -  person Publius    schedule 09.09.2012
comment
Да. Если вы вызываете функцию constexpr, используя в качестве аргументов неконстантные выражения, функция выполняется во время выполнения. В моем примере, поскольку вы принудительно сохраняете результат в типе constexpr, вы получаете ошибку компиляции, поскольку это невозможно сделать во время компиляции. PS: почему вы смеетесь над моей фамилией?   -  person mfontanini    schedule 09.09.2012
comment
Я не смеялся над этим. Я просто набирал ni слишком много раз, поэтому, чтобы указать, что я не пытался правильно назвать ваше имя и потерпел неудачу, я просто набрал явно неправильное количество ni. Также спасибо за ответ: функции, объявленные constexpr, не должны компилироваться во время компиляции. Если хотите, можете отправить это как ответ, и я его приму.   -  person Publius    schedule 09.09.2012
comment
Не волнуйтесь, я не обиделась: P. Просто балуюсь с тобой.   -  person mfontanini    schedule 09.09.2012


Ответы (3)


Если вы вызываете функцию constexpr, используя в качестве аргументов неконстантные выражения, функция выполняется во время выполнения.

Если вы сделаете это:

constexpr someType dummy = fma(someType(), someType(), someType());

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

Обратите внимание, что это будет работать, если вы предоставите конструктор constexpr и constexpr operator+/* в someType.

person mfontanini    schedule 09.09.2012

Из раздела 7.1.5.6 стандарта C ++ 11:

If the instantiated template specialization of a constexpr function template or member function of a class
template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that
specialization is not a constexpr function or constexpr constructor. [ Note: If the function is a member
function it will still be const as described below. — end note ] If no specialization of the template would
yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.

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

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

person Vaughn Cato    schedule 09.09.2012

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

person Dani    schedule 09.09.2012