From: Jens Maurer (Jens.Maurer_at_[hidden])
Date: 2001-01-28 17:56:18


Here are a few initial comments. They should not discourage you, but
point out a few things for your further consideration.

jbandela_at_[hidden] wrote:
> Here is some code, that allows assigning and manipulating variables
> without knowing the exact type, but by knowing what expression
> produced them.

In general, the STL approach to that problem is by defining another
function call layer where the unknown type is a template parameter.
It is deduced during overload resolution, and the type of the
argument expression is thus "known" (rather instantiated) in the
function body. I do, however, recognize that it would be useful
to avoid that additional layer in some circumstances. Unfortunately,
the examples exposed are not template-heavy enought to really show
the benefit, which would possibly become more apparent when
expressions yield very complicated types, as those in expression
templates.

 - Please separate implementation (header file) from test/example program.
 - The whole thing needs boost-ification and documentation.
 - I'd like to see a feature comparison between this proposal and
the (boost-accepted) "any" class by Kevlin Henney.

> class Destructor{};

Needs a virtual destructor, I believe.
 
> template<class T>
> struct DestructorImp:public Destructor

Should be in namespace "boost::detail" and be referenced from the
"Memento" class internally.

> std::allocator<T> a;
> a.destroy(static_cast<T*>(o));

Is there any benefit from using std::allocator<> instead
of calling the destructor explictly right away, such as so:
  static_cast<T*>(o)->~T()
?

> template<class T>
> DestructorImp<T> GetDestructor(void* o, const T*){

The "const T*" parameter is superfluous, you can use explicit function
template instantiation. Yes, MSVC is broken in this regard, but
can be worked around.

> template<int sz>
> struct Memento{
> char mem_[sz];
> void* data_;
>
> template<class T>
> Memento(const T& object){
> T* o = new(static_cast<void*>(&mem_[0])) T(object);
> data_ = o;

_data will always contain &mem_[0] and is thus superfluous.

You need to cater for alignment requirements, which you don't currently.

> #define BOOST_TYPE(expr) (0?GetType((expr)):0)

Boost has been very reluctant in defining new function-style macros. Any
such macro needs a strong justification that its purpose cannot be fulfilled
with "normal" C++, e.g. templates. I'd like to see this justification
explicitly.
 
> #define BOOST_LET(var, expr,line) Memento<sizeof(expr)> var
> (expr);Destructor dd##line = GetDestructor(var.data_,BOOST_TYPE
> (expr)) ;

This is entirely unsatisfactorily, because it interferes with
conditional statements not containg a block.

  if( /* ... */ )
    BOOST_LET(...); // oops

Besides, the destruction can be integrated in Memento and then, I
believe, looks suspiciously like the "any" class.

Plus, explicitly requiring a "line" parameter is too error-prone.

> for(;y.get(BOOST_TYPE(v.begin())) != v.end();++y.get
> (BOOST_TYPE(v.begin())) )

This looks rather awkward to me, compared to a simple typedef
and a straightforward loop.

It would be really helpful if, given some expression "expr", the
type of this expression could be made available as a name, so
that
  typedef BOOST_TYPE(2.0*3) T;
gives you "double" for T.

This is why we need "typeof" in the core language.

Jens Maurer