Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forwarding all constructors in C++0x

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...) {}
};
like image 255
Neil G Avatar asked Jun 25 '10 17:06

Neil G


People also ask

What is perfect forwarding C++?

What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.

Can we inherit constructors in C++?

To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them. Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.

How do you call a constructor from another constructor in C++?

No, in C++ you cannot call a constructor from a constructor. What you can do, as warren pointed out, is: Overload the constructor, using different signatures. Use default values on arguments, to make a "simpler" version available.

How are constructors called in inheritance?

For multiple inheritance order of constructor call is, the base class's constructors are called in the order of inheritance and then the derived class's constructor.


2 Answers

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.

like image 177
Johannes Schaub - litb Avatar answered Sep 27 '22 20:09

Johannes Schaub - litb


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.

like image 36
Dennis Zickefoose Avatar answered Sep 27 '22 20:09

Dennis Zickefoose