Say I want to build a graph at compile time, using some algorithm, and then count how many nodes ended up in the graph. This seems like an ideal situation for constexpr, rather than template metaprogramming, since the goal is a computation that yields a value, rather than really being about types. I have some code that works, but the feature is so new I'm afraid the compilers are being lenient, and I could interpret part of the standard as saying I can't do this.
#include <iostream>
struct A { int x; constexpr A(int i) noexcept : x{i} {} };
struct B { A& a; constexpr B(A& a) noexcept : a{a} {} };
constexpr int foo() {
A a{55};
B b{a};
return b.a.x;
}
template<int N>
void output()
{
std::cout << N << std::endl;
}
int main() {
// to be absolutely sure compile time eval'd,
// pass as template arg
constexpr auto b = foo();
output<b>();
}
Both the a
and b
instances are created at compile time, and they have the same lifetime so this should be "safe". But a
is a non-static object, and this part of the standard seems to say that's not allowed:
An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints, or it is a function.
So can I or can't I? GCC and clang are both fine with it.