Рассмотрим следующий код:
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. Но это компилируется просто отлично. Почему это?
Я использую G ++ компилятор MinGW с опцией -std = c ++ 0x.
Если вы вызываете функцию constexpr, используя в качестве аргументов неконстантные выражения, функция выполняется во время выполнения.
Если вы делаете это:
constexpr someType dummy = fma(someType(), someType(), someType());
это не удастся, так как вы заставляете результат быть сохраненным в constexpr
тип. Это не может быть сделано во время компиляции, поэтому вы получаете ошибку компиляции.
Обратите внимание, что это было бы работать, если вы предоставили как constexpr
конструктор и constexpr
operator+/*
в someType
,
Из раздела 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 ухудшается до функции non-constexpr, если он создается с параметрами шаблона, которые делают его недопустимой функцией constexpr.
Если это не будет действительная функция constexpr, независимо от того, какие параметры шаблона вы ей предоставили, компилятор может пожаловаться, но это не обязательно.
Поскольку шаблоны в основном проверяются на наличие ошибок при использовании, только если вы используете их с типом без операторов constexpr, произойдет ошибка.