std :: make_shared не работает, но создание указателя с использованием «new» работает нормально - PullRequest
0 голосов
/ 23 сентября 2019

Я сейчас создаю систему графического интерфейса для своего игрового движка.Я попытался создать общий указатель для одного из компонентов "GUImovingbar", используя std::make_shared(), но получил следующую ошибку при компиляции

'std :: shared_ptr <_Other> std :: make_shared (_Types &&...) ': не удалось вывести аргумент шаблона для' _Types && ... 'из' списка инициализаторов '

Однако, когда я использовал те же самые входные данные для создания нового указателя, он компилировалсяхорошо без ошибок.Это показалось мне немного странным.Что мне здесь не хватает?

Код с использованием 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 && ...) ': не удалось вывести аргумент шаблона для «_Types && ...» из «списка инициализаторов»

Следующее не вызывает ошибок вообще:

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;

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Проблема заключается в агрегатной инициализации, которую вы выполняете в вызове make_shared.Если вы создаете объект с new GUImovingbar(...), вы напрямую вызываете конструктор, и, таким образом, компилятор точно знает, какой аргумент какого типа.Это позволяет вам агрегировать инициализировать указанные аргументы.

Однако, если вы вызываете make_shared, все аргументы должны быть выведены из значения, которое вы передаете в функцию (потому что это шаблон).В основном это будет выглядеть так:

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

Как компилятор должен знать, какой это тип на самом деле?

Если вы все еще хотите использовать make_shared, вы должны явно инициализировать типы с помощьюих имена.

0 голосов
/ 23 сентября 2019

Как шаблонная функция, std::make_shared пытается найти подходящий конструктор для вашего класса, учитывая параметры, которые он имеет.Поскольку вы дали ему списки инициализаторов (содержимое в скобках), он не понимает, какой тип эти списки должны инициализировать, и поэтому не может найти соответствующий конструктор.Однако при правильном использовании конструктора неоднозначность устраняется, поскольку благодаря положению параметров компилятор знает, какой тип списки предполагается инициализировать, и соответствующим образом преобразует их.

Если вы все еще хотите использовать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 }))

...