C++14: Инициализация переменных constexpr из значений параметров
Скажем, у меня есть класс, который может возвращать константное выражение через constexpr
функция:
template<int N>
struct Foo {
constexpr int Bar() const { return N; }
};
Если бы я хотел инициализировать значения constexpr из Foo::Bar()
как передать параметр типа Foo
? Я попробовал эти два, с примером constexpr
переменная внутри каждого, чтобы проверить, что это может быть инициализировано:
template<int N>
constexpr int ByValue(Foo<N> f) {
constexpr int i = f.Bar();
return f.Bar();
}
template<int N>
constexpr int ByReference(const Foo<N> &f) {
constexpr int i = f.Bar();
return f.Bar();
}
constexpr int a = ByValue(Foo<1>{});
constexpr int b = ByReference(Foo<1>{});
Но Clang 3.7 вызывает ошибку на ByReference
пока gcc >=5.1 не работает: живая демоверсия
main.cpp:15:25: error: constexpr variable 'i' must be initialized by a constant expression
constexpr int i = f.Bar();
^~~~~~~
main.cpp:22:25: note: in instantiation of function template specialization 'ByReference<1>' requested here
constexpr int b = ByReference(Foo<1>{});
Какая разница между принятием const Foo &
или равнина Foo
, когда Bar
является constexpr
в любом случае и возвращает действительное константное выражение?
Что правильно и почему, GCC или Clang? Если возможно, ссылки на стандарт будут приветствоваться.
1 ответ
§5.20:
Ссылка не имеет предшествующей инициализации с точки зрения i
Впрочем: это параметр. Один раз инициализируется ByReference
называется.
Давайте удалим constexpr
от i
декларации и рассмотрим вызов ByReference
в целом:
template<int N>
constexpr int ByReference(const Foo<N> &f) {
int i = f.Bar();
return i;
}
constexpr int j = ByReference(Foo<0>());
Это хорошо, так как f
имеет предшествующую инициализацию. Инициализатор f
также является константным выражением, поскольку неявно объявленный конструктор по умолчанию constexpr
в этом случае (§12.1/5).
следовательно i
инициализируется константным выражением, а вызов сам является константным выражением.