Search code examples
c++variadic-templatesshared-ptr

`std::make_shared` fails for empty parameter pack


Background

I have a variadic class template.

template<typename... Ts>
class Foo {
public:
    Foo(Ts... values) {
        
    }    
};

Using this class, I can create objects with/without parameters.

Foo<int> f1{1};
Foo<int, double> f2{1, 2.0};
Foo f3{};

I can even create a shared pointer.

auto f4 = std::make_shared<Foo<int, double>>(1, 2.0);

Problem

The problem arises the moment I want to create a shared pointer without parameters. Neither of these approaches work:

auto f5 = std::make_shared<Foo>();
Foo f5{}
auto f5_sharedPtr = std::make_shared(std::move(f5));
main.cpp:27:37: error: no matching function for call to ‘make_shared class Foo>()’
     auto f5 = std::make_shared<Foo>();
                                     ^
In file included from /usr/include/c++/7/memory:81:0,
                 from main.cpp:9:
/usr/include/c++/7/bits/shared_ptr.h:703:5: note: candidate: template std::shared_ptr<_Tp> std::make_shared(_Args&& ...)
     make_shared(_Args&&... __args)
     ^~~~~~~~~~~
/usr/include/c++/7/bits/shared_ptr.h:703:5: note:   template argument deduction/substitution failed:

Questions

  1. Can someone explain what's going on here?
  2. Does anyone know how to make this work?

Solution

  • The correct syntax is std::make_shared<Foo<>>()

    Foo<int,double> is a type, which is why std::make_shared<Foo<int,double>> works.

    The problem is that Foo, without the <> is a template, and is not a type, and results in a compilation error.

    Edit:

    The code

    Foo f3{};
    

    is sort of a special case. In this case, your are using the C++17 feature Class Template Argument Deduction. This deduces the type of f3 as Foo<> This is also what lets you write

    Foo f4{1, 2.0}
    

    Which would deduce the type of f4 as a Foo<int, double>.

    The cppreference page gives more examples of when this feature can be used