Boost logo

Boost :

From: Greg Chicares (chicares_at_[hidden])
Date: 2001-07-18 21:32:14

Michael Kenniston wrote:
> template< typename Rep, typename Tag >
> struct constant
> {
> constant() {}
> operator Rep() const; // fully specialized for each Rep/Tag pair
> };

> - there are no "static-initialization-order" issues, because the static
> variables contain no data to initialize

Does this solve the initialization order problem? Consider

> namespace double_constants
> {
> constant< double, pi_tag > const pi;
> constant< double, e_tag > const e;
> }

The 'constant' struct has a nontrivial constructor, so the lifetime of
'pi' begins begins when its constructor finishes. If we add at global
scope in a different source file

  double global_pi_squared = std::pow(double_constants::pi, 2);

and the compiler chooses to initialize that before 'pi', then 'pi' is
converted to an rvalue, but isn't that undefined behavior?

Can that be fixed by removing the user-defined constructor from
'constant' and the const-qualifier from 'pi'? We don't care whether
'pi' is constant as long as its operator Rep() is.

> Here's the general idea (tested under MSVC6 and g++2.95.3-4):

If you write 'template<>' before the four lines like this one:

inline constant< float, pi_tag >::operator float() const { return 3.14F;}

then it compiles OK with
  Comeau C/C++
  gcc-3.0x (2001-06-26 CVS)
  borland C++ 5.5.1

Also suggest removing unused argument 'dummy' from
  void show_all( const T & dummy, const char * label )

> Well, ok, if you /really/ want defaults, I guess you could replace
> the master declaration of the conversion operator with something like:
> operator Rep() const { return Rep( constant< long double, Tag >() );
> }

Specifying the value once with maximal precision and relying on standard
floating-point conversions is an attractive idea. But the value you get
can depend on the hardware direction, at least on an 80x87, so it can
change during program execution.

Boost list run by bdawes at, gregod at, cpdaniel at, john at