4

When I read the source code of Hypodermic, I found an empty structure declared in the constructor of its container. I don't understand why it did this?

class Container : public std::enable_shared_from_this< Container >
{
   private:
     struct PrivateKey {};
   
   public:
     Container(const PrivateKey&,
                  const std::shared_ptr< IRegistrationScope >& registrationScope,
                  const std::shared_ptr< IRuntimeRegistrationBuilder >& runtimeRegistrationBuilder)
            : m_registrationScope(registrationScope)
            , m_runtimeRegistrationBuilder(runtimeRegistrationBuilder)
     {
     }

     static std::shared_ptr<Container> create(const std::shared_ptr<IRegistrationScope>& registrationScope,
                                                   const std::shared_ptr<IRuntimeRegistrationBuilder>& runtimeRegistrationBuilder)
     {
        return std::make_shared<Container>(PrivateKey(), registrationScope, runtimeRegistrationBuilder);
     }

     // other code...
};

PrivateKey is defined in the above code, I don’t understand what problem it solves. It doesn't seem to do anything.

candycat
  • 435
  • 4
  • 13
  • 1
    @underscore_d You can see the entire code through the link below:https://github.com/ybainier/Hypodermic/blob/master/Hypodermic/Container.h – candycat Jul 13 '20 at 10:39
  • I don't see any reason for this, they could have just declared the ctor as private. – Sebastian Hoffmann Jul 13 '20 at 10:44
  • Possibly used to solve some sort of member address alignment issue? – Adrian Mole Jul 13 '20 at 10:47
  • @AdrianMole No, definitely not. – user253751 Jul 13 '20 at 10:56
  • 7
    The constructor cannot be declared as private, because the `std::make_shared` needs public access and cannot be made a friend (because of extra dependencies). So the Private Key Idiom is used by the class static factory function, which calls `std::make_shared`, and has access to the private key as a token to access the public constructor. – Eljay Jul 13 '20 at 11:09
  • 2
    FYI: This answer to [SO: how to block usage of std::make_shared](https://stackoverflow.com/a/58016110/7478597) provides a use case for the constructor with argument of `private` type. – Scheff's Cat Jul 13 '20 at 11:12
  • @Scheff Good link, basically a dupe IMHO. – underscore_d Jul 13 '20 at 11:13

1 Answers1

1

As @Eljay stated in a comment, the constructor has to be accessible when using std::make_shared.

The idea behind this factory method is to make sure no component will get an instance of Container that is not a std::shared_ptr thus enforcing the legitimacy of shared_from_this() inside Container methods.

If you need further explanation, feel free to reach me through GitHub.

mister why
  • 1,967
  • 11
  • 33