Когда я объявляю шаблонный класс, я могу использовать любые аргументы шаблона не типа в constexpr функций-членов, таких, как это:функция член Constexpr возвращает параметр шаблона не считается constexpr при доступе через ссылку
template <int Value>
struct Foo {
constexpr int value() const { return Value; }
};
затем я могу использовать эту функцию позже инициализировать constexpr переменные следующим образом:
template <int Value>
void use_value(Foo<Value> foo) {
constexpr int baz{ foo.value() };
}
int main() {
Foo<10> bar;
use_value(bar);
}
то, что я не понимаю, что когда я беру foo
по ссылке ...
template <int Value>
void use_value(Foo<Value>& foo) { // by ref
constexpr int baz{ foo.value() };
}
int main() {
Foo<10> bar;
use_value(bar);
}
... clang скажет мне, что foo.value()
не является постоянным выражением!
test.cpp:8:24: error: constexpr variable 'baz' must be initialized by a constant expression
constexpr int baz{ foo.value() };
~~^~~~~~~~~~~~~
test.cpp:13:5: note: in instantiation of function template specialization 'use_value<10>'
requested here
use_value(bar);
Почему это происходит? Имеет ли он какое-то отношение к факту, что в первом примере компилятор смог следить за всем временем жизни foo
, тогда как при взятии по ссылке какая-то другая часть программы могла бы изменить экземпляр, как-то влияя на constexprness foo.value()
? Хотя здесь явно не так (учитывая специализацию шаблона, нет возможности изменить значение Value
), я не уверен, действительно ли вы могли бы «разрушить» функции constexpr-члена, вмешавшись в экземпляр в середине его исполнение в некоторых случаях.
Редактировать
Хорошо, так что ссылки плохо для constexpr, так как они имеют место во время выполнения - и значения constexpr жестко закодированы в результате исполняемый файл. Как насчет постоянной ссылки? Это работает:
int main() {
constexpr int foo2{5};
int const& bar2{ foo2 };
}
Но с Foo
класса, это не поможет изменить ссылку на const
:
template <int Value>
void use_value(Foo<Value> const& foo) { // const ref
constexpr int baz = foo.value();
}
я получаю ту же ошибку компилятора. В чем тут разница?
Если 'Foo :: value' должно возвращать' значение', вы должны просто его создать, а затем использовать эту статическую функцию в 'use_value' (и полностью отбросить параметр foo). – Rumburak
Согласен, это просто глупый пример, чтобы продемонстрировать, что я имею в виду. Он не пытается понять смысл программирования. – user1685094
Ну, в конце концов, ссылка - это просто указатель со слегка отличающейся семантикой. Для 'constexpr' вам нужны значения ... – Rumburak