3

I am not really getting any smarter from these error messages.

Minimal (not) Working Example on godbolt

#include <initializer_list>
#include <memory>
#include <vector>


struct S
{
    int j;
    double y;
    std::vector<int> data;
    S(int i, double x, std::initializer_list<int> list)
    : j(i)
    , y(x)
    , data(list)
    {

    }
};

int main()
{
    auto ptr = std::make_shared<S>(1, 1.2, {1,2,3}); // I want this to work
// auto ptr = std::make_shared<S>(1, 1.2, std::initializer_list<int>({1,2,3})); // works
}

Errors:

<source>:22:35: error: too many arguments to function 'std::shared_ptr<_Tp>  std::make_shared(_Args&& ...) [with _Tp = S; _Args = {}]'
   22 |     auto ptr = std::make_shared<S>(1, 1.2, {1,2,3});

<source>:11:5: note: candidate: 'S::S(int, double, std::initializer_list<int>)'
   11 |     S(int i, double x, std::initializer_list<int> list)
      |     ^
<source>:11:5: note:   candidate expects 3 arguments, 0 provided

It compiles fine, when I call the explicit constructor for std::initializer_list<int> in front of {1,2,3}. Is there a way to circumvent this, so my std::make_shared does not bloat so much?

infinitezero
  • 1,610
  • 3
  • 14
  • 29
  • Does this answer your question? [std::shared\_ptr and initializer lists](https://stackoverflow.com/questions/11820981/stdshared-ptr-and-initializer-lists) – InUser Feb 16 '22 at 08:29
  • Related: [std::make\_shared with std::initializer\_list](https://stackoverflow.com/questions/24234480/stdmake-shared-with-stdinitializer-list) and https://stackoverflow.com/questions/26379311/calling-initializer-list-constructor-via-make-unique-make-shared – user17732522 Feb 16 '22 at 08:39
  • No, as can bee seen in my code, I know how to make it work, with a work-around. I want to know how I can use it in the crisp, short form. – infinitezero Feb 16 '22 at 08:40
  • @infinitezero You cannot use `std::make_shared` with just braces as argument. You would need to create a function taking the correct parameter types for the `S` constructor, forwarding to `std::make_shared`. – user17732522 Feb 16 '22 at 08:41

1 Answers1

3

{1,2,3} can be multiple things, and make_shared has no possibility of knowing what it is at the time parameter pack is expanded. If you don't want to state the long std::initializer_list<int>{1,2,3} explicitly, the easiest solutions would be: a. shortening the type's name: using ints=std::initializer_list<int>; b. wrapping the call:

auto make_shared_S(int x, double y, std::initializer_list<int> l)
{
    return std::make_shared<S>(x, y, l);
}

Demo: https://godbolt.org/z/WErz87Ks4

alagner
  • 3,448
  • 1
  • 13
  • 25