Параметры функций constexpr сами по себе не являются объектами constexpr, поэтому их нельзя использовать в константных выражениях.Оба ваших примера, возвращающие array
s, плохо сформированы, потому что к ним нет действительного вызова.
Чтобы понять почему, рассмотрим этот бессмысленный пример:
struct Z { int i; constexpr int operator()() const { return i; }; };
template <int V> struct X { };
template <typename F> constexpr auto foo(F f) -> X<f()> { return {}; }
constexpr auto a = foo(Z{2});
constexpr auto b = foo(Z{3});
Z
имеетconstexpr
оператор вызова, и это правильно сформировано:
constexpr auto c = Z{3}();
static_assert(c == 3);
Но если бы было разрешено более раннее использование, у нас было бы два вызова на foo<Z>
, которые должны были бы вернуть другойтипы .Это могло произойти, только если фактическое значение f
было параметром шаблона.
Обратите внимание, что компиляция объявления clang сама по себе не является ошибкой компилятора.Это класс ситуаций, которые плохо сформированы, диагностика не требуется.