Boost logo

Boost :

From: Jim Apple (japple_at_[hidden])
Date: 2004-01-27 18:10:30


value_initialized has non-deep (shallow?) const semantics. const
value_initialized<T> is supposed to be const. Unfortunately, due to
compiler errors in VC++ and Borland, it has

operator T &() const

instead of

operator T&()
operator const T&() const

which breaks const-correctness in a big way.

I'd like for there to be a config macro that identifies this error. I
would make one, as well as a test for it, myself, but I only have access
to icc and gcc on linux, both of which pass the test, so it's hard
trying to identify the extent of the overloading selection failure.

After creating this macro, we could use it to make a const correct
value_initialized class for users with more advanced compilers.

For those compilers, I think there would be value to adding operator->
for the invocation of member functions, like boost::optional.

As an alternative, deep-copy would break const expectations in generic
functions that take a const T &, but it would preserve it elsewhere, so
it may be worth some more thought.

Finally, I have come up with a similar class (which I wrote with deep
const sematics, although I am open to argument about shallow const) for
solving the following problem:

----------------------------------------------------------------------
#include <iostream>

template<typename T>
struct wrap {
   static const T joe;
};

template<typename T>
const T wrap<T>::joe;

struct call_out {
   int num;
   call_out() : num(77) {}
};

template<typename T>
struct check_call {
   check_call() {
     std::cout << wrap<T>::joe.num << std::endl;
   }
};

check_call<call_out> x;

int main(){}
-----------------------------------------------------------------------

This outputs 0, not 77, on gcc 3.3.2, intel 8, and vc6. I don't know if
that's correct, 14.7.1/1 says:
 

"... in particular, the initialization (and any associated side effects)
of a static data member does not occur unless the static data member is
itself used in a way that requires the definition of the static data
member to exist."

If this is std-conforming behavior, or not, i have a workaround that allows:
------------------------------------------------------------------------
#include <iostream>
#include "can_init.hpp"
 

template<typename T>
struct wrap {
   static can_init<const T> joe;
};
 

template<typename T>
can_init<const T> wrap<T>::joe;
 

struct call_out {
   int num;
   call_out() : num(77) {}
};
 

template<typename T>
struct check_call {
   check_call() {
     wrap<T>::joe.ensure_init();
     std::cout << wrap<T>::joe->num << std::endl;
   }
};
 

check_call<call_out> x;
 

int main(){}
-----------------------------------------------------------------------
which obviously uses deep const. Is there any interest in including this
in boost/utility/? Should it have shallow or deep const semantics?

Jim


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk