I hope to prevent the users from creating new instance through the constructor, so I mark the constructor as a private method.
What's more, I need to provide a method to return an object which is used to automatically manage the life of the instance.The function in the code snippet below is getFoo()
.
Here is the code snippet which I wrote at first:
#include <iostream>
#include <memory>
class Foo : public std::enable_shared_from_this<Foo> {
private: //the user should not construct an instance through the constructor below.
Foo(int num):num_(num) { std::cout << "Foo::Foo\n"; }
public:
~Foo() { std::cout << "Foo::~Foo\n"; }
std::shared_ptr<Foo> getFoo() { return shared_from_this(9); }
private:
int num_;
};
Since the constructor is marked as private, so there is no way to create an instance, which causes getFoo
could never be called. So I updated the code snippet above.
Here is the code snippet:
#include <iostream>
#include <memory>
class Foo : public std::enable_shared_from_this<Foo> {
private: //the user should not construct an instance through the constructor below.
Foo(int num):num_(num) { std::cout << "Foo::Foo\n"; }
public:
~Foo() { std::cout << "Foo::~Foo\n"; }
static std::shared_ptr<Foo> Create() { return std::make_shared<Foo>(5); }
private:
int num_;
};
int main() {
auto pf = Foo::Create();
}
But it does not compile, indeed. Here is what the compiler complains:
In file included from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/alloc_traits.h:33,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/ext/alloc_traits.h:34,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/basic_string.h:40,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/string:53,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/locale_classes.h:40,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/ios_base.h:41,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/ios:42,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/ostream:38,
from /opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_Tp*, _Args&& ...) [with _Tp = Foo; _Args = {int}]':
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/alloc_traits.h:635:19: required from 'static void std::allocator_traits<std::allocator<void> >::construct(allocator_type&, _Up*, _Args&& ...) [with _Up = Foo; _Args = {int}; allocator_type = std::allocator<void>]'
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/shared_ptr_base.h:604:39: required from 'std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<void>; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]'
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/shared_ptr_base.h:971:16: required from 'std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = Foo; _Alloc = std::allocator<void>; _Args = {int}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]'
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/shared_ptr_base.h:1712:14: required from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<void>; _Args = {int}; _Tp = Foo; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]'
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/shared_ptr.h:464:59: required from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<void>; _Args = {int}; _Tp = Foo]'
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/shared_ptr.h:1009:14: required from 'std::shared_ptr<typename std::enable_if<(! std::is_array< <template-parameter-1-1> >::value), _Tp>::type> std::make_shared(_Args&& ...) [with _Tp = Foo; _Args = {int}; typename enable_if<(! is_array< <template-parameter-1-1> >::value), _Tp>::type = Foo]'
<source>:9:68: required from here
/opt/compiler-explorer/gcc-12.1.0/include/c /12.1.0/bits/stl_construct.h:119:7: error: 'Foo::Foo(int)' is private within this context
119 | ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:6:5: note: declared private here
6 | Foo(int num):num_(num) { std::cout << "Foo::Foo\n"; }
| ^~~
It really surprises that Create()
could not call the private constructor. I think any member function should have the allowance to invoke another private member variable. If I miss something, please let me know.
Note: I only could use C 11
.
Five minutes later, I realise where am I wrong. Create()
is not a member function, it's a static function. It's legal that it could not call the non-static member function :(
CodePudding user response:
You can make the shared yourself. Will this work for you?
#include <iostream>
#include <memory>
class Foo : public std::enable_shared_from_this<Foo> {
private: //the user should construct an instance through the constructor below.
Foo(int num):num_(num) { std::cout << "Foo::Foo\n"; }
public:
~Foo() { std::cout << "Foo::~Foo\n"; }
static std::shared_ptr<Foo> Create() {
Foo *foo = new Foo(5);
return std::shared_ptr<Foo>(foo);
}
private:
int num_;
};
int main() {
auto pf = Foo::Create();
}