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>();