为什么编译器不能从 std::make_shared 中推导出模板参数?

Why the compiler cannot deduce the template arguments from std::make_shared?

我在“C++ 入门,第 5 版”中的练习中遇到了这个简单的问题:

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.

我试过了,看到了一些答案和建议,但我还没有被说服。

有人说:

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.

但我自己试过这段代码:

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;
}

如您所见,我的 make_vec 可以在没有显式模板参数的情况下工作,而 make_shared() 则不能。这是为什么?

std::make_shared 长得像

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

之所以需要提供 T 是因为无法从 Args 知道要创建什么类型的对象。假设你有

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

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

然后你做

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

无法知道您应该创建 Foo1 还是 Foo2,因此您需要提供要创建的对象类型。

对于 std::make_shared 的大多数变体,其中 return 是 std::shared_ptr<T>std::shared_ptr<U[]> - 没有参数具有类型 T。示例:

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

(在后一个例子中,对于某些 UT 必须是 U[])。

如果这些函数没有类型 T 参数 - 你怎么能推导出 T(或 U)?

在你的例子中,你接受类型T的参数并且可以很容易地推导出模板参数。