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.