Каково использование constexpr для функции non-const member?
Принятый ответ в литеральной ошибке компиляции класса с конструктором и функцией constexpr (отличается vc, g++) показывает, что в С++ 14 существует разница в том, как constexpr int A::a()
и constexpr A::a() const
. т.е. constexpr
в функции-члене не означает, что функция не изменяет объект, на котором он действует.
Данный пример:
struct A {
constexpr A() {}
constexpr int a() {return 12; }
constexpr int b() const {return 12; }
};
int main()
{
constexpr A a;
// DOES NOT COMPILE as a() is not const
// constexpr int j = a.a();
const int k = a.b(); // Fine since b() is const
}
Мне constexpr
на a()
кажется бесполезным. Существует ли конкретное использование для constexpr
для constexpr
[const11] non- const
?
Ответы
Ответ 1
Вопрос: как вы создаете массив constexpr размером 1024
когда все элементы установлены в 0
кроме элемента 42
элемента, который должен быть 11
?
#include <array>
constexpr auto make_my_array() -> std::array<int, 1024>
{
std::array<int, 1024> a{};
a[42] = 11; // std::array::operator[] is constexpr non-const method since C++17
return a;
}
auto test()
{
constexpr std::array<int, 1024> a = make_my_array();
}
Или лучшее предложение от @michael-anderson make_iota_array
:
template <std::size_t N>
constexpr auto make_iota_array() -> std::array<int, N>
{
std::array<int, N> a{};
for (std::size_t i = 0; i < N; ++i)
a[i] = i;
return a;
}
Ответ 2
constexpr
означает, что "может использоваться, когда требуется постоянное выражение". "Подразумеваемая константа" для объявленных объектов не означает, что мы не можем иметь неконстантные объекты в других контекстах. Например, несколько надуманный пример, созданный из вашего собственного:
template<int>
struct foo {
};
struct A {
int i = 0;
constexpr A() {}
constexpr int a() { return i; }
constexpr int b() const {return 12; }
constexpr A& c() { ++i; return *this; }
};
int main()
{
foo<A{}.c().a()> f1;
}
Очевидно, что аргумент шаблона должен быть постоянным выражением. Теперь A{}
является prvalue литерального типа с constexpr c'tor, а это неконстантный объект. Функция-член имеет право изменять эту "константу", потому что все вычисление может свернуть к постоянному выражению во время компиляции. Это обоснование правил, на одной ноге.