On 9 June 2011 12:26, Andy Gibbs wrote: > Hi, > > I've been playing around with constexpr in gcc 4.6 and have a question: > > This works: > > template <int v> struct wrapper > { enum : int { value = v }; }; > > constexpr int test1(int a) > { return a; } > > constexpr int test2(int a) > { return test1(a); } > > constexpr int one = 12; > constexpr int two = wrapper<test2(one)>::value; > > > But this doesn't work: > > constexpr int test3(int a) > { return wrapper<test1(a)>::value; } > > constexpr int three = test3(one); > > > The compiler error is: > > In function 'constexpr int test3(int)': > error: 'a' is not a constant expression > note: in template argument for type 'int' > > > The question I have is: why doesn't (or can't) the second case work? In > function 'test2' the compiler believes 'a' is a constant expression and the > declaration of variable 'two' shows 'wrapper' can take a constexpr as its > template parameter, so is it just an oversight of the compiler that 'test3' > doesn't compile? Or is it intentional? I'm not certain, but I think the compiler's right. A constexpr function isn't one which can *only* be a constant expression, it's one which is potentially a constant-expression when used in the right context (e.g. given only constants as arguments.) You can call test1 and test2 with non-constant arguments, and they act like normal functions. Or you can call them with constants and they can appear in constant expressions. test3 cannot be used like a normal function. > I understand that test3 would not compile if passed a non-constexpr > parameter, whereas test2 would compile -- but this is what I would want: > this way I can stop test3 being used except during compile-time. Or is > there a better way of doing this? Make the int parameter a template parameter, so it has to be known at compile-time. template<int A> constexpr int test3() { return wrapper<test1(A)>::value; } constexpr int three = test3<one>();