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
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

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

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

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.


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)
        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;
        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


           David Abrahams * Boost Consulting
dave_at_[hidden] *

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