This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: constexpr question
- From: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- To: Andy Gibbs <andyg1001 at hotmail dot co dot uk>
- Cc: gcc-help at gcc dot gnu dot org
- Date: Thu, 9 Jun 2011 13:52:11 +0100
- Subject: Re: constexpr question
- References: <BLU0-SMTP1655B12149EB26CA53D1E98E7650@phx.gbl>
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>();