0

I have this simple question from an exercise in "C++ primer, 5th ed":

Exercise 16.38: When we call make_shared (§ 12.1.1, p. 451), we have to provide an explicit template argument. Explain why that argument is needed and how it is used.

I've tried, then I've seen some answers and suggestions, but I'm not convinced yet.

Some said:

The argument is probably need for the return type which cannot be deduced from the arguments supplied in the function call (i.e. make_shared<int> returns a shared_ptr<int>).

Alternatively the function body of make_shared needs to know what type to allocate to dynamic memory which is not deducible from the arguments supplied.

But I've tried this code on my own:

template <typename T>
std::vector<T> make_vec(T x...)
{
    return std::vector<T>(x);
}

int main()
{
   auto vi = make_vec(77);
   std::cout << vi.size() << std::endl;
}

As you can see, my make_vec works without explicit template arguments, while make_shared() cannot. Why is that?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Maestro
  • 2,512
  • 9
  • 24

2 Answers2

3

std::make_shared looks like

template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );

And the reason T needs to be provided is because there is no way to know from Args what type of object to create. Lets say you have

struct Foo1
{
    Foo1(int, int) {}
};

struct Foo2
{
    Foo2(int, int) {}
};

And then you do

auto foo_ptr = std::make_shared(42, 42);

There is no way to know if you should create a Foo1 or a Foo2, so you need to provide the type of object you want to create.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
2

For most variants of std::make_shared which return a std::shared_ptr<T> or std::shared_ptr<U[]> - no parameter has type T. Examples:

template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
template<class T>
shared_ptr<T> make_shared( std::size_t N );

(where in the latter example, T must be U[] for some U).

Without a type-T parameter to those functions - how can you deduce T (or U)?

In your example, you do take a parameter of type T and can easily deduce the template argument.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • I got it! As I've re-read your example I've seen that the type parameter T cannot be deducible from the arguments in the call thus it must be explicitly specified. is it right? – Maestro Nov 19 '20 at 21:49
  • Thank you so much! – Maestro Nov 19 '20 at 21:51
  • 1
    Yes, that's right. Next time, please take a little more time to look at the official declarations of library functions - scrutinizing them often makes things clearer. – einpoklum Nov 19 '20 at 22:00
  • Yep I do agree with it. Thanks. – Maestro Nov 19 '20 at 22:02