The accepted answer in literal class compile error with constexpr constructor and function (differ vc, g++) shows that in C++14 there is a difference in the way constexpr int A::a()
and constexpr A::a() const
can be used. i.e. constexpr
on a member function does not imply that the function does not change the object it acts on.
The given example is:
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
}
To me the constexpr
on a()
seems useless.
Is there a concrete use for constexpr
on a non-const
member function?
Question: how do you create a constexpr array of size 1024
with all elements set to 0
except element element 42
which needs to be 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();
}
Or a better yet suggestion from @michael-anderson a 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;
}
constexpr
means "can be used where a constant expression is required". The "implied const" for declared objects doesn't mean we can't have non-const objects in other contexts. For instance, a somewhat contrived example, created from your own:
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;
}
Obviously the template argument must be a constant expression. Now, A{}
is a prvalue of a literal type with a constexpr c'tor, and it's a non-const object. The member function is allowed to modify this "constant" because the entire computation can collapse to a constant expression at compile time. That's the rationale for the rules, on one foot.