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.
constexprfunction does not have to produce a compile time constant. It can do that when supplied with compile time constant arguments (if any). Not sure about your case though. But the presented code doesn't exercise the compile time constant-ness.A a{55};may beconstexpr,B b{a};cannot be (with clang error messagenote: reference to 'a' is not a constant expression) Demo