must_be_shared is a class that forces classes derived from std::enable_shared_from_this to be managed by std::shared_ptr.
- Replace
std::shared_ptrwithmust_be_shared. - Place the constructor in
public. - Add
const magic_t& _in the first argument of the constructor. - Add
must_be_shared<XXX>(_)in the constructor initializer. (XXXis your class name) - Set the second and subsequent arguments of the constructor to the creation function
create().
It requires that the constructor be placed public, but it is not possible to create it locally, as there is no way to create a magic_t as public.
#include "must_be_shared.h"
class FOO : public must_be_shared<FOO> {
private:
int foo_value_;
public:
FOO(const magic_t& _, int foo_value):
must_be_shared<FOO>(_),
foo_value_(foo_value)
{}
void foo() {
auto instance = shared_from_this();
std::cout << "foo -> " << instance->foo_value_ << std::endl;
}
};
class BAR : public FOO {
private:
int bar_value_;
public:
BAR(const magic_t& _, int bar_value = 100, int foo_value = 200):
FOO(_, foo_value),
bar_value_(bar_value)
{}
void bar() {
auto instance = shared_from_this_as<BAR>();
std::cout << "bar -> " << instance->bar_value_ << std::endl;
}
};
int main() {
// compile error
// auto foo = FOO(FOO::magic_t{FOO::_magic_seed{}}, 1);
// basic
auto foo = FOO::create(1);
foo->foo();
// derived class
auto bar = BAR::create<BAR>(10, 20);
bar->foo();
bar->bar();
// You can use default arguments
auto bar_default = BAR::create<BAR>();
bar_default->foo();
bar_default->bar();
// If you want to manage with a base class
auto bar_as_foo = BAR::create<BAR, FOO>(10, 20);
bar_as_foo->foo();
// bar_as_foo->bar(); // <-- compile error
bar_as_foo->shared_from_this_as<BAR>()->bar();
}
// foo -> 1
// foo -> 20
// bar -> 10
// foo -> 200
// bar -> 100
// foo -> 20
// bar -> 10