constexpr w/c++ stdlib features??

Jonathan Wakely
Fri May 23 09:17:00 GMT 2014

On 22/05/14 22:01 -0700, Linda A. Walsh wrote:
>Jonathan Wakely wrote:
>>>    I thought that since vector or valarray could have dimensions
>>>specified at compile time,
>>This has dimensions specified at compile-time:
>> int* p = new int[5];
>But I had the contents and declared the immutable.  That's a bit different.


  const int* const p = new int[5]{ 0, 1, 2, 3, 4 };

Still requires what C++ calls 'dynamic initialization' *even* *if* the
compiler can fold it. Because of that it is forbidden to declare it

  constexpr const int* auto p = new int[5]{ 0, 1, 2, 3, 4 };

>The compiler "could" take the const and constexpr at face value and put
>the strings in the R/O section and an array of pointers in the form 'valarray'
>or 'vector' uses at run time, and put that in whatever structure they use,
>all in the program/r-o segment, before the program runs.  Then when it
>runs it would use those values out of R/O storage.  In places where "knowing"
>that they were "#define's", the compiler could further do compile time

We don't use that sort of language here. The advantage of constexpr is
the compiler knows the value is a compile-time constant expression, no
more #d-e-f-i-n-e  ;-)

>strength reductions and optimizations possibly eliminating the need for some
>of the original data to even be loaded.

Yes, yes, yes, the compiler can do that, but it's an optimization, not
something mandated by the C++ standard as a requirement for compilers
to do.

>I.e. That's what I was "hoping" would be done.  C++ is what, 20-30 years old now?
>One could hope that it would have moved more smarts into the compiler, no?

Declaring an object 'constexpr' means its initialization is
*guaranteed* to be done at compile-time, by any conforming C++
compiler. For that to work there have to be restrictions on what is
allowed in the initialization of a constexpr object. Dynamic
allocation is about as far away from the things allowed at
compile-time as you can get.

If you declare a const std::vector a smart compiler might be able to
optimise away the storage. If you declare a constexpr std::vector a
compiler is *required* to give a diagnostic because you've violated
the rules of C++.

You can't use constexpr std::vector. Period.

>	But that's the point.  If the compiler *can* reduce it at
>compile time because all inputs are known, then it's like constant-folding
>or loop-strength reductions.  That is code that doesn't have to be
>executed the way it is written at run-time because it can be optimized
>out.  I don't see why it is "impossible" for this to not be considered the
>same type of optimization.

The standard says so.

>	While C++11 book says that the compiler must throw an error if it
>cannot evaluate it at compile time.  I assert that since it is possible to
>do in 'C', the same treatment of static placement into the same form used by
>vector and such, at run time, could be used.  It's a form of constant folding.

You're comparing apples and oranges. A C++ std::vector is not an
array, to keep claiming "it is possible to do it in C" is nonsense.
Try writing a struct in C that is dynamically allocated and returned
from a function and then tell me C can turn that into a compile-time
constant which is usable where the language requires a

>(Which isn't to say a compiler *has* to implement it nor that it is trivial,
>simply that it should be possible, no?).


What you tried to do is not possible with std::vector. Period.

The standard says which constructors are 'constexpr' and which are
not, and it forbids implementations from adding 'constexpr' elsewhere.
The constructor you tried to use is not declared 'constexpr' in the
standard. The standard says that to declare an object 'constexpr' it
must be a 'literal type' which std::vector is not.

That is not a limitation of our implementation.

This is getting further and further off-topic for this list. If you
want to debate what constexpr should allow please take it elsewhere.

>>Optimisations are not supposed to change semantics, and declaring an
>>object constexpr has semantics that guarantee no non-trivial
>>initialization, it doesn't mean "please try to avoid non-trivial
>>initialization if the compiler happens to be smart enough and I enable
>	I consider constant folding and C-initializations to be trivial.

Again, apples and oranges. C doesn't have constexpr. C doesn't have
constructors. C doesn't have destructors.

>That they are in a more complicated data structure is a side-effect of c++ being
>a more complex language, but in that framework, one could still call such
>compile time resolution of structures "trivial" (i.e. once it is done, it is
>trivial for everyone).

Only for suitably trivial structures, which C++ calls literal types.
std::vector is not such a type. Period.

>>>    It *seemed*, that by tagging things as invariant (either at compile
>>>or run time after some initialization), it could allow 
>>>optimizations.  in this
>>>case, it would be the run-time code to initialize "resources" that are
>>>statically fixed before the program starts execution.
>>A const vector is invariant at run-time after some initialization.
>>A constexpr object cannot have any run-time initialization. At all.
>	The expressions I listed didn't need any AFAICT...

Using std::vector does. Period.

You've been shown how to turn your C code into C++11 using constexpr,
this is not the right place to argue about what you think constexpr
should mean.

More information about the Libstdc++ mailing list