3

I do not understand why this works fine:

std::array<double, 2> someArray = {0,1};
std::shared_ptr<MyClass> myobj = std::make_shared<MyClass>(someArray);

But this does not work:

std::shared_ptr<MyClass> myobj = std::make_shared<MyClass>({0,1});

Compiler says:

too many arguments to function ‘std::shared_ptr< _Tp> std::make_shared(_Args&& ...)
...
candidate expects 1 argument, 0 provided

Question: Can someone clarify why this happens and if there is any way I can fix the second approach without defining an extra variable?


Edit: Example of MyClass:

#include <memory> //For std::shared_ptr
#include <array>
#include <iostream>

class MyClass{
  public:
    MyClass(std::array<double, 2> ){
      std::cout << "hi" << std::endl;
    };
};

2
  • 1
    What is MyClass? Commented Sep 27, 2019 at 16:27
  • 1
    ... and what does its constructors look like? Commented Sep 27, 2019 at 16:27

2 Answers 2

5

Braced initializers {} can never be deduced to a type (in a template context). A special case is auto, where it is deduced to std::initializer_list. You always have to explictly define the type.

auto myobj = std::make_shared<MyClass>(std::array<double, 2>{0, 1});
Sign up to request clarification or add additional context in comments.

1 Comment

auto myobj = std::make_shared<MyClass>(std::array{0., 1.}); would be fine too.
-1

The type of {0, 0} is context-dependent. If {0, 0} is being used to immediately construct another object of known type, then it represents a prvalue of that object type:

MyClass m({0, 0}); 

Here, {0, 0} refers to a prvalue of type std::array<double, 2> On the other hand, if there are no constraints on the type, then {0, 0} refers to an initializer list of type std::initializer_list<int>:

auto vals = {0, 0};

There's no way to initialize MyClass from std::initializer_list<int>, so make_shared fails to compile:

MyClass m(vals); // Fails: can't construct MyClass from initializer list

How does this connect to std::make_shared? Because std::make_shared is a template, {0, 0} isn't being used to construct a specific type. As a result, it's treated as a std::initializer_list.

3 Comments

This is not correct. {0, 0} is only a std::initializer_list<int> when used with auto. Without it has no type
Isn’t it also a std::initiaizer_list when passed to a templated function?
No. A special rule was added for auto so it could work (still not sure if I like that or not). No rule was put in place for template deduction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.