std::make_shared 不工作,但使用 "new" 创建指针工作正常

std::make_shared not working, but creating the pointer using "new" works fine

我目前正在为我的游戏引擎制作一个 GUI 系统。我尝试使用 std::make_shared() 为组件 "GUImovingbar" 之一创建共享指针,但在编译时出现以下错误

'std::shared_ptr<_Other> std::make_shared(_Types &&...)': could not deduce template argument for '_Types &&...' from 'initializer list'

然而,当我使用完全相同的输入来创建一个新指针时,它编译得很好,没有错误。这让我觉得有点奇怪。我在这里错过了什么?

代码使用 std::make_shared():

this->playerhullbar = std::make_shared<GUImovingbar>(
    "right",
    { 50,hully }, //scoords
    globalguitextures[findStringSrdPointerPairVectElement(globalguitextures, "barbackground")].second,
    { 0,static_cast<double>(maxplayerhullint),static_cast<double>(maxplayerhullint) },
    { 50,hully,250, hully,2,100 },//for int vector input ("bsbebdbc"): 1  barxstart, 2  y , 3 barendx, 4 y, 5 distance between bars in px, 6 bar count
    { 0,255,0 },
    bartextvect
    );

以上导致错误:

'std::shared_ptr<_Other> std::make_shared(_Types &&...)': could not deduce template argument for '_Types &&...' from 'initializer list'

以下完全不会导致错误:

std::shared_ptr<GUImovingbar> newptr(new GUImovingbar(
    "right",
    { 50,hully}, //scoords
    globalguitextures[findStringSrdPointerPairVectElement(globalguitextures, "barbackground")].second,
    { 0,static_cast<double>(maxplayerhullint),static_cast<double>(maxplayerhullint) },
    { 50,hully,250, hully,2,100 },//for int vector input ("bsbebdbc"): 1  barxstart, 2  y , 3 barendx, 4 y, 5 distance between bars in px, 6 bar count
    { 0,255,0 },
    bartextvect)
); 
this->playerhullbar = newptr;

作为模板函数,std::make_shared 尝试根据给定的参数为您的 class 找到合适的构造函数。因为你已经给了它初始化列表(括号中的东西),所以它对这些列表应该初始化什么类型感到困惑,因此它找不到合适的构造函数。然而,当你使用正确的构造函数时,歧义就被消除了,因为由于参数的位置,编译器知道列表应该初始化什么类型,并相应地转换它们。

如果您仍想使用 std::make_shared,则必须通过将初始化列表的类型放在列表之前来消除歧义:

this->playerhullbar = std::make_shared<GUImovingbar>(
    "right",
    Scoords { 50,hully },
    globalguitextures[findStringSrdPointerPairVectElement(globalguitextures, "barbackground")].second,
    Rect { 0,static_cast<double>(maxplayerhullint),static_cast<double>(maxplayerhullint) },
    std:vector<int> { 50,hully,250, hully,2,100 },
    Color { 0,255,0 },
    bartextvect
);

(或者,如果你有一个旧的编译器,也使用带括号的前一种语法:std:vector<int>({ 50,hully,250, hully,2,100 })

问题在于您在 make_shared 调用中进行的聚合初始化。如果您使用 new GUImovingbar(...) 创建一个对象,您将直接调用构造函数,因此,编译器确切地知道哪个参数是哪种类型。这使您能够聚合初始化所述参数。

但是,如果您调用 make_shared,则所有参数都必须从您传递给该函数的值中推导出来(因为它是一个模板)。这基本上是这样的:

auto x = {10, "hello", 4};

编译器应该如何知道这实际上是什么类型?

如果您仍想使用 make_shared,则必须使用名称显式初始化类型。