views:

186

answers:

2

What is the correct way to forward all of the parent's constructors in C++0x?

I have been doing this:

class X: public Super {
    template<typename... Args>
        X(Args&&... args): Super(args...) {}
};
+1  A: 

I think you need to do Super(std::forward<Args>(args)...) if you want things forwarded properly. args has a name, so I believe it will bind to regular references before rvalue references.

More importantly, though, you won't be forwarding copy constructors this way. The compiler will still generate one for you, because it doesn't consider template constructors. In the example provided, you're okay, because the compiler generated one will just call the parent copy constructor anyhow, which is exactly what you want. If that's not appropriate in a more complicated case, then you'll have to write it yourself.

Dennis Zickefoose
`Super(std::forward<Args>(args)...)` is correct, so you were pretty close. Remember, forward requires explicit template argument.
DeadMG
I had that originally, then I second guessed myself. Thanks for the correction.
Dennis Zickefoose
This is great. Do you have an intuition on what std::forward does? (Is it first-order?) Why can't we just write "args..."? Would that result in copy constructors being called?
Neil G
Because if any of them are rvalue references (and the constructor you're calling expects such) then attempting to pass them on will cause problems because they're now lvalue references (they have names).
Noah Roberts
+6  A: 

There is a better way in C++0x for this

class X: public Super {
  using Super::Super;
};

If you declare a perfect-forwarding template, your type will behave badly in overload resolution. Imagine your base class is convertible from int and there exist two functions to print out classes

class Base {
public:
  Base(int n);
};

class Specific: public Base {
public:
  template<typename... Args>
    Specific(Args&&... args);
};

void printOut(Specific const& b);
void printOut(std::string const& s);

You call it with

printOut("hello");

What will be called? It's ambiguous, because Specific can convert any argument, including character arrays. It does so without regard of existing base class constructors. Inheriting constructors with using declarations only declare the constructors that are needed to make this work.

Johannes Schaub - litb
IMHO - this is the answer that should have been accepted even though the other directly answers the question asked.
Noah Roberts
Thanks Johannes.@Noah Roberts: Yes.
Neil G
I am just wondering if the `explicit` keyword would not make the call unambiguous while at the same time allow the perfect forwarding template to work. Not that I would recommend automagically generating derived constructors...
David Rodríguez - dribeas