Consider polymorphic classes with a base object, a derived interface, and a target:
// base object struct object { virtual ~object() = default; }; // interfaces derived from base object struct interface1 : object { virtual void print_hello() const = 0; template<typename T> static void on_destruction(object* /*ptr*/) { std::cout << "interface1::on_destruction" << std::endl; } }; // final object struct derived1 : interface1 { virtual void print_hello() const override { std::cout << "hello" << std::endl; } static std::string get_type_name() { return "derived1"; } };
In real use, end objects are defined through a plug-in system, but this is not so. Please note that I want to be able to call on_destruction when the object is destroyed (see register_object below). I want to use these classes as follows:
int main() {
Using std :: unique_ptr to manage objects, I got the following code for register_object :
template<typename T> using unique = std::unique_ptr< T, std::function<void(object*)> // object deleter >; namespace { std::map< std::string, std::function<unique<object>(void)> > factory_map; } template<typename T> void register_object() { factory_map.emplace( T::get_type_name(), []() { unique<T> instance{ new T, [](object* ptr) { T::on_destruction<T>(ptr); delete ptr; } }; return static_move_cast<object>( std::move(instance) ); } ); }
And the create * functions:
unique<object> create_unique_object(const std::string& type_name) { auto f = factory_map.at(type_name); return f(); } template<typename T> unique<T> create_unique(const std::string& type_name) { return static_move_cast<T>( create_unique_object(type_name) ); }
You notice in register_object and create_unique call to static_move_cast , which is declared as:
template<typename U, typename T, typename D> std::unique_ptr<U, D> static_move_cast ( std::unique_ptr<T, D>&& to_move_cast ) { auto deleter = to_move_cast.get_deleter(); return std::unique_ptr<U, D>{ static_cast<U*>( to_move_cast.release() ), deleter }; }
The purpose of static_move_cast is to enable static_cast on std :: unique_ptr when moving the deleter during translation. The code works, but I want to hack std :: unique_ptr. Is there a way to reorganize the code to avoid my static_move_cast ?