Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2001-06-14 09:53:50


----- Original Message -----
From: Luis Pedro Coelho <deepblack9_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Thursday, June 14, 2001 11:26 AM
Subject: Re: [boost] A little utility class I'd like to contribute to boost

> Em Quarta, 13 de Junho de 2001 23:43, escreveste:
> <snip>
> > > template <typename T, T init = T()>
> >
> > Given the intended usage for this class, I think that the 'init' value
> > should be always given.
> > This removes the 'default constructible' requirement on T imposed by the
> > default initialization of 'init'.
>
> My usage of this has always been with builtin types so that has never been
a
> problem. In general, I think value classes should have default
constructors,
> so I do not see this as a problem.

But the assumption that the template argument will have a def. ctor. (even
though it will be the general case)
is unnecesary because I wouldn't write:
   auto_init<int> n ;
since it is useless.
If the requirement for T is actually unnecesary it should be there.

>
> > > struct auto_init {
> > > auto_init():object(init) { }
> > > auto_init(const T& other):object(other) { }
> > > operator T& () { return object; }
> > > operator const T& () const { return object; }
> > > T& operator = (const T& other) { object = other; return
object; }
> > > void reset() { object = init; }
> > > private:
> > > T object;
> > > };
> >
> > Since you are providing conversion operators, the constructor for T
should
> > be explicit.
> > Therefore, auto_init's own copy constructor and assigment should also be
> > present.
> >
> > But there are other important issues to be addressed:
> > Ideally, auto_init<T> objects should inherit the semantics of the inner
> > type T,
> > such as other operators (==,+,&, void const*, etc...) but that's tricky,
> > because T might not support some of the them.
> > Otherwise I won't be able to write expressions like: if ( data == 3 ),
> > int a = data + 1 , int* p = &data, if ( data ) ..., etc...
> <snip>
>
> There except for the taking of the address, all other cases are handled by
> the conversion to T operator. For example, "if (data == 3)" gets
transformed
> into "if (data.operator int() == 3)", so no problems there.
>

This is true for built-in types, but not for the general case.
The problem is that in the above expressions the implicit conversion from
auto_init<T> to T is performed, but not the implicit conversion from T
to the destination type.
As I stated, this can be solved if the operators are explicitely defined,
but then
there is the problem of which ones to define.

This example should explain what I am referring to:

// Declared just what I need to show the problem.
template<class T> struct MyNumberType
{
  operator T const& () const ;
} ;

template<class T> struct auto_init
{
  operator T const&() const ;
} ;

int main()
{
  MyNumberType<int> MyInt;

  // These are valid due to the implicit conversions from MyNumberType to
int and bool.
  ( MyInt == 0 ) ;
  ( MyInt + 1 ) ;
  if ( MyInt ) ;

  auto_init< MyNumberType<int> > Auto ;

  // These fail because it would require a 'cascaded' implicit conversions:
from auto_init<> to MyNumberType<> to int.
  ( Auto == 0 ) ;
  ( Auto + 1 ) ;
  if ( Auto ) ;
}

Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com


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