Why can't make_shared construct this object?

//auto foo = std::shared_ptr<Foo>(new Foo(i)); "works"

Here you access Foo's constructor from inside Foo and then pass this pointer to std::shared_ptr, which is fine.

auto foo = std::make_shared<Foo>(i);

Here std::make_shared tries to access Foo's constructor which is protected and thus not allowed.


@SombreroChicken provided a good answer why this is the case. I want to provide a possible solution

#include <iostream>
#include <memory>

class Foo {
private:
    struct Token{};
public:
    std::shared_ptr<Foo> getFoo(int i) {
        auto foo = std::make_shared<Foo>(i, Token{});
        //auto foo = std::shared_ptr<Foo>(new Foo(i)); "works"
        return foo;
    }
    Foo(int i, Token) : Foo(i) {}

protected:
    Foo(int i) {std::cout << "foo" << std::endl; }
};

int main(int argc, const char * argv[]) {

}

it works by making a public constructor that requires something only Foo can make, so anyone who received the 'token' can call the constructor

NOTE: passing such tag parameters may be better done as the first parameter, because

  1. to be consistent with standard library

  2. certain compilers (notably msvc) have special handling of it that improves compile times

Tags:

C++