Search code examples
c++templatesc++17

How to forward constructor arguments for class template


Consider a sort of default Bar:

struct Bar
{
};

and a specific case of a Bar, MyBar, which has a constructor that requires an int:

struct MyBar
{
    MyBar(int n){}
};

I then have a class that uses a Bar:

template<class ThisBar = Bar> struct Foo : ThisBar
{
    Foo(double){}; // Construct the 'Foo' from a 'double'
};

A snag though is that if I want a Foo<MyBar> I need to be able to construct the MyBar:

Foo<MyBar> f(1.0, 1);

where the int is used to construct the MyBar. My question is how do I write this constructor, so the below compiles in C++17?

int main()
{
    Foo<MyBar> f(1.0, 1);
}

Solution

  • You can create a templated constructor and forward the template arguments:

    #include <utility>
    
    struct Bar
    {
    };
    
    struct MyBar
    {
        MyBar(int n){}
    };
    
    template<class ThisBar = Bar> struct Foo : ThisBar
    {
        template <typename... Ts>
        Foo(double, Ts&&... ts)
         : ThisBar(std::forward<Ts>(ts)...) 
        {};
    };
    
    int main()
    {
        Foo<MyBar> f(1.0, 1);
    }
    

    https://godbolt.org/z/WjfosqYqn