Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-08-20 12:32:07


Hi All,

A question from one of my Boost.Python users (see
http://mail.python.org/pipermail/c++-sig/2002-August/001946.html
http://mail.python.org/pipermail/c++-sig/2002-August/001947.html)
prompted me to think seriously about this problem:

  "How can we write generic code which constructs new objects?"

[I've cc'd Andy Koenig here because he's responsible for
value-initialization, which comes into this conversation. I've cc'd Herb
because, well, maybe he's already written a GOTW on this one]

I have to admit, I don't know the rules, but they seem terribly nonuniform
to me. The specific problem I'm trying to solve is the implementation of
boost/python/implicitly_convertible.hpp:

    template <class Source, class Target>
    void implicitly_convertible();

    Requires: The expression Target(s), where s is of type Source, is
valid.

Internally, this function needs to do a placement-new of the target type.
Naturally, I thought that internally writing:

    new (storage) Target(src)

would work. However, that doesn't work for all types. For example, if src
is an int and Target is an enum type, I can write:

    Target x = Target(src);

but not:

    Target* p = new Target(src);

That's just wierd. The only solution I know is:

    Target* p = new Target(Target(src));

but then that requires copy-constructibility of Target. So I think
ultimately, I need to do some kind of compile-time dispatching to determine
the type category of Target, only using this copy-construction workaround .
Do we even have a single type trait that covers it? I don't think so,
unless is_scalar<> includes is_enum<> (that's not evident from our docs).

A related issue comes up when you want to convert from one type to another,
but only if the source type can be implicitly converted to the target.
Writing:

    Target(src)

works unless Target is a builtin, in which case this seems to act just like
a dangerous C-style cast. This makes me nervous about using explicit
construction in any generic code.

    enum Foo { foo = 42 };
    template <class T> void f(T const&);
    template <class Src, Target> int g(Src const& x)
    {
        f(Target(x));
        return 0;
    }
    int x = g<Foo>(4.4); // OK

I guess I could use a named variable instead:

    template <class Src, Target> int g(Src const& x)
    {
        Target t = x;
        f(t);
        return 0;
    }

Is that the best answer?

Finally, there's the issue of default construction. If I want to
generically declare a default-constructed object of type T, I can't write:

    T x;

since builtins (and I presume, enums) won't be initialized. I can't write:

    T x();

since that just declares a function. What can/should I write?

And finally, the $60,000 question: is there a library solution for these
problems?

-Dave

-----------------------------------------------------------
           David Abrahams * Boost Consulting
dave_at_[hidden] * http://www.boost-consulting.com


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