$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Douglas Gregor (gregod_at_[hidden])
Date: 2002-07-01 21:11:10
On Monday 01 July 2002 09:06 pm, David Abrahams wrote:
> Oh, this is spooky. I am just implementing similar functionality in v2 of
> the Boost.Python library. In v1 it was called from_python.
>
> The problem: a Python object (usually managed via a PyObject*, but in
> Boost.Python managed with the wrapper class object) can in principle hold
> any C++ type. A major component of the Boost.Python library's functionality
> is the extraction of C++ objects from Python objects, and the wrapping of
> C++ objects into Python objects.
>
> So, should I call my from_python function variant_cast<> as well? I don't
> think that reads well. In particular, I think of a cast as generally being
> a peer-to-peer type transformation, whereas these "casts" are
> container-to-containee transformations. I was thinking of "extract":
>
>     extract<int>(obj)
>
> Now, "extract<>" might be too-general a name to use in namespace boost, but
> I'm not sure that it is. I do think it works better than "variant_cast<>".
>
> Thoughts?
> Dave
Very interesting. I'm most interested in the peer-to-peer vs. 
container-to-containee classification, because that really decides whether 
"extract" or "variant_cast" is the better name. 
How do we classify the relationship between a variant type and the value in 
that variant type? Is the variant type just a holder for another type, or is 
the variant type one of those other types, but with the decision made at 
compile-time? Thinking in object-oriented terms, is a variant like this:
  class Variant { /* ... */ };
  class IntegerValuedVariant : public Variant { /* ... */ };
  class FloatValuedVariant : public Variant { /* ... */ };
Or is a variant more like this:
  class VariantValue { /* ... */ };
  class Variant {
  public:
    VariantValue* value;  
    // ...
  };
  class IntegerValuedVariant : public VariantValue { /* ... */ };
  class FloatValuedVariant : public VariantValue { /* ... */ };
With the first view, a downcast from a Variant to one of the values it may be 
is a peer-to-peer transformation, so if we think of a variant like this then 
I believe variant_cast is the right name.
With the second view, a variant is a container-of-one. The name "extract" 
makes perfect sense here, because it is accessing the only value in the 
container. 
I personally favor the first view, and therefore the name variant_cast. With 
the variant type we're describing (I'll get to PyObject* in a moment...), I 
think of the favorite expression example:
  class Plus;
  class Minus;
  typedef variant<Plus, Minus, double> expression;
Does the 'expression' type contain an expression or is it an expression? OO 
textbooks would tell us to write the object hierarchy like this:
  class Expression { /* ... */ };
  class Plus : public Expression { /* ... */ };
  class Minus : public Expression { /* ... */ };
  class Literal : public Expression { /* ... */ };
Why? Because Plus is-a(n) Expression, and a Literal is-a(n) Expression. 
With PyObject*, I think it is the same question. A PyObject* is a just a 
placeholder for a type we can't determine statically (like 'Expression' in 
the hierarchy above). When we know the type dynamically, we cast to that 
type, just like we would dynamic_cast in the OO style. 
PyObject*, variant, any -- they're all just union types. Is a union a 
container of one?
        Doug