gpt4 book ai didi

c++ - std::make_shared 与 std::initializer_list

转载 作者:IT老高 更新时间:2023-10-28 22:19:53 28 4
gpt4 key购买 nike

#include <iostream>
#include <memory>

class Base
{
public:
Base() {}
};

class Derived : public Base
{
public:
Derived() {}
Derived(std::initializer_list<std::pair<int, std::shared_ptr<Base>>>) {}
};

int main(int argc, char ** argv)
{
auto example = new Derived({
{ 0, std::make_shared<Derived>() }
});

return 0;
}

它正常工作( live preview ),但是当我尝试使用 std::make_sharedstd::initializer_list 作为参数时,我得到了错误:

auto example = new Derived({
{ 0, std::make_shared<Derived>({
{ 0, std::make_shared<Derived>() }
}) }
});

正如您在 live preview 上看到的那样.

error: too many arguments to function...

只有当我这样做时它才有效(live preview):

auto example = new Derived({
{ 0, std::make_shared<Derived>(std::initializer_list<std::pair<int, std::shared_ptr<Base>>> {
{ 0, std::make_shared<Derived>() }
}) }
});

我想知道的是:为什么只有当我将 std::initializer_list 作为参数传递给 std::make_shared 而不是使用 { {}} 就像这样:

auto example = new Derived({ { 0, std::make_shared<Base>() } });

是否可以让 std::make_shared 接受它?

提前致谢。

最佳答案

原因

auto example = new Derived({
{ 0, std::make_shared<Derived>() }
});

有效的是编译器知道它必须匹配初始化器

{{ 0, std::make_shared<Derived>() }}

不知何故与构造函数

Derived::Derived(std::initializer_list<std::pair<int, std::shared_ptr<Base>>>) {}

所以很明显初始化列表的元素,

{ 0, std::make_shared<Derived>() }

需要用于初始化std::pair<int, std::shared_ptr<Base>> .然后它找到一个包含两个元素的对的构造函数,

pair::pair (const first_type& a, const second_type& b);

在哪里 first_typeintsecond_typestd::shared_ptr<Base> .所以最后我们看到参数 std::make_shared<Derived>()隐式转换为 std::shared_ptr<Base> ,我们可以开始了!

在上面,我指出编译器通过寻找一个构造函数来处理初始化列表,该构造函数直接接受初始化列表或适当数量的参数,然后在适当的隐式转换后将初始化列表的元素传递给该构造函数如有必要。例如,编译器可以确定您的 std::shared_ptr<Derived>需要隐式转换为 std::shared_ptr<Base>在上面的例子中只是因为对的构造函数需要它。

现在考虑

std::make_shared<Derived>({
{ 0, std::make_shared<Derived>() }
})

问题是make_shared<Derived>是一个部分专用的函数模板,可以接受任意数量和类型的参数。因此,编译器不知道如何处理初始化列表

{{ 0, std::make_shared<Derived>() }}

重载解析时不知道需要转换成std::initializer_list<std::pair<int, std::shared_ptr<Base>>> .此外,braced-init-list 永远不会被推导出为 std::initializer_list<T>通过模板扣除,所以即使你有类似的东西

std::make_shared<Derived>({0, 0})

Derived有一个合适的构造函数采用 std::initializer_list<int> ,它仍然无法工作,原因相同:std::make_shared<Derived>将无法为其参数推断出任何类型。

如何解决这个问题?不幸的是,我看不到任何简单的方法。但至少现在你应该知道为什么你写的东西不起作用了。

关于c++ - std::make_shared 与 std::initializer_list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24234480/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com