Goxman
Goxman

Reputation: 3

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

I am currently making a GUI system for my game engine. I tried to create a shared pointer for one of the components "GUImovingbar" using std::make_shared() but got the following error when compiling

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

However, when I used the exact same inputs to create a new pointer, it compiled fine with no errors. This struck me as a bit odd. What am I missing here?

Code using 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
    );

Above causes error:

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

The following causes no errors at all:

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;

Upvotes: 0

Views: 2232

Answers (2)

Timo
Timo

Reputation: 9825

The problems are the aggregate initializations that you're doing in the make_shared call. If you create an object with new GUImovingbar(...) you are directly calling the constructor and thus, the compiler knows exactly which argument is of which type. This enables you to aggregate initialize said arguments.

However, if you call make_shared all arguments must be deduced from the value that you pass to the function (because it's a template). This would basically be like this:

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

How should the compiler know what type this actually is?

If you still want to use make_shared you have to explicitly initialize the types with their names.

Upvotes: 0

Thomas B&#233;cavin
Thomas B&#233;cavin

Reputation: 113

As a template function, std::make_shared tries to find the appropriate constructor for your class given the parameters it has. Since you've given it initializer lists (the stuff in brackets), it is confused about what type those lists are supposed to initialize, and it thus can't find the appropriate constructor. However, when you use the constructor proper, ambiguity is removed, since thanks to the parameters' position the compiler knows what type the lists are supposed to initialize, and it converts them accordingly.

If you still want to use std::make_shared, you'll have to disambiguate the types of the initializer lists by putting them before the list :

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

(or, if you have an old compiler, use the former syntax with parentheses as well : std:vector<int>({ 50,hully,250, hully,2,100 }))

Upvotes: 1

Related Questions