constexpr w/c++ stdlib features??

Linda A. Walsh
Fri May 23 05:02:00 GMT 2014

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.

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
strength reductions and optimizations possibly eliminating the need for some
of the original data to even be loaded.

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?

> That doesn't make it a compile-time constant, it uses dynamic
> allocation which is inherently a run-time behaviour.
When the dynamic allocation occurs is not exactly specified -- only
that it occurs before you use it, and after you've requested it.  One
could argue that it's been requested at compile time, therefore, it's
a perfectly valid optimization.  If the user didn't want a constexpr, they
shouldn't be using "#define"... I.e. There's no requirement that #defines
be evaluated at run time -- usually they evaluate at compile time, but at
the same time, I don't believe there is a requirement that #defines all
reduce to simple constants at compile time either.  I.e. at "-O0" a compiler
*might* not even do constant folding, no?

>> then they might support compile time constants
>> as well.  I didn't know the implementation couldn't use compile time
>> dimensions to allow it to be used as constexpr.
>>     Is it a requirement that std::vector use runtime allocation if
>> the object it is representing is fixed at compile time or is that an
>> the result of implementation?
> It's not possible for std::vector to tell the difference, so it's not
> possible to implement it to choose to avoid run-time allocation.
	It would be up to the compiler to know that the user has requested
constexpr and provided the final initialization list.

> As far as I'm aware the standard does not forbid the compiler from
> optimising away dynamic allocation if it can statically prove there
> will be no user-visible difference, but that would be a property of
> the compiler not std::vector, and still wouldn't let you use
> constexpr, because being able to declare the object as constexpr would
> be a user-visible difference.
	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.

	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.
(Which isn't to say a compiler *has* to implement it nor that it is trivial,
simply that it should be possible, no?).

> 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
> optimisations".
	I consider constant folding and C-initializations to be trivial.
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).

>>     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...

> Or use std::array
Will have to look at this further as I gain more experience.

One thing that is confusing:


> You can even turn the former into the latter (using
> make_index_sequence from C++14):

	The Stroustrup book I have from 2014 is for C++11, um,
WTF is C++14?!?


> There are loads of ways to skin this cat, but constexpr std::vector is
> not one of them.
Well, I won't learn unless I ask, :-)...

>>     I'm trying to recode parts of this program in C++ specific
>> terms where it will decomplicate the code.  Since it seems doable in 'C',
>> I wanted to figure out how to have C++ do it.
> You can do what you did in C, that's valid C++ too.
> (If it ain't broken don't fix it.)
	Yeah yeah...

	But in some cases, replacing the C code with C++ can be pleasing...
Instead of forloops to copy elements of an array, I can simple use assignment
on the valarray, or add them together.  That can really simplify code when
it works.

> Adding constexpr then changing to a non-trivial type is not the C++
> way to do it, because it's not valid C++!
Hmrumph!... ;-)

Thanks for the insight about how I am beating my head against the wall...;-)

More information about the Libstdc++ mailing list