Dear Readers!

There are times when one needs to use the private constructor of a class with one of the smart pointer generating standard library functions, but unfortunately it is not so straightforward to do so. Let’s examine a simple case:

C++

1
2
3
4
5
6
7
8
9
10
// someclass.h

class SomeClass {
public:
    static std::shared_ptr<SomeClass> getInstance();
    // other funtions
    
private:
    SomeClass();
};

C++

1
2
3
4
5
6
7
8
9
// someclass.cpp

std::shared_ptr<SomeClass> SomeClass::getInstance()
{
    auto instance = std::make_shared<SomeClass>();
    // do something with instance
    
    return instance;
}

This looks valid, except for the fact that the std::make_shared function doesn’t have access to the private constructor of SomeClass, and as such it cannot instantiate it. The compiler error message tells us the same:

make

1
2
/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/unique_ptr.h:825:30: error: ‘SomeClass::SomeClass()’ is private within this context
{ return shared_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

Fortunately, a simple workaround for this problem exists with a bit of inheritance trickery:

C++

1
2
3
4
5
6
7
8
9
10
// updated someclass.cpp

std::shared_ptr<SomeClass> SomeClass::getInstance()
{
    struct MkShrdEnablr : public SomeClass {};
    auto instance = std::make_shared<MkShrdEnablr>();
    // do something with instance
    
    return instance;
}

By adding a temporary class into the getInstance() function, that inherits from SomeClass , we achieve what was originally intended. Please also notice that the existence of a temporary class is not exposed to the outside world, as the returned type is still a pointer to SomeClass, so everything gets converted back to the original class as soon as the function returns.

Thus, today’s lesson is:

Use a temporary subclass to make a connection between a smart pointer generator function and a class with a private constructor.