-1

Here are some subclasses that derive from the abstract class:

class obj
{
  public:
    virtual std::string type() = 0;
};

class subobj01 : public obj
{
  public:
    std::string type() override
    {
        return "subobj01";
    }
};

class subobj02 : public obj
{
  public:
    std::string type() override
    {
        return "subobj02";
    }
};

class subobj03 : public obj
{
  public:
    std::string type() override
    {
        return "subobj03";
    }
};

Now I want to define a function that does the following,

// pseudo-code
type create_instance(std::shared_ptr<obj> o)
{
    if (o->type() == "subobj01")
        return std::make_shared<subobj01>();
    else if (o->type() == "subobj02")
        return std::make_shared<subobj02>();
    else if (o->type() == "subobj03")
        return std::make_shared<subobj03>();
}

I don't know if this can be achieved using template metaprogramming. Thanks!


Update: I know I can use std::dynamic_pointer_cast to convert pointers manually.

In fact, obj and subobjxxx are defined by third-party libraries (I shouldn't modify them). I just want to implement a wrapper to do the pointer conversion automatically, without manually specifying the type.

J.W Kang
  • 115
  • 7
  • `auto` will fail because the return types of different branches diffeer, but you can specify that your function returns a `std::shared_ptr` and rely on the fact that `std::shared_ptr` et al implicitly convert to `std::shared_ptr` (assuming you make them publically inherit from the abstract class instead of privately) – Nathan Pierson Aug 27 '22 at 07:23
  • 2
    Adding a virtual `clone` method to each class would probably be simpler. Otherwise fixing the return type is all you need to do to make your function work i think – Alan Birtles Aug 27 '22 at 07:28
  • If you didn't do it with smart pointers, but used plain non-owning pointers (like `obj* o` and `return new subobj1;`), how would you solve it then? What would your return-type be then? What makes you think it would be different when using smart pointers? – Some programmer dude Aug 27 '22 at 07:39
  • 1
    Simply use the abstract factory pattern with a map. Maybe this will help: https://stackoverflow.com/questions/71635517/c-polymorphism-factory-how-to-build-function-object-from-its-string-name-and-m/71636312#71636312 – A M Aug 27 '22 at 08:06
  • Why do you want to create a fresh object of the same type as an existing object? In what real-life situation is this useful? – n. m. could be an AI Aug 27 '22 at 08:21

1 Answers1

0

All you need to do is to replace type in the return type with std::shared_ptr<obj> which all the std::shared_ptr<subobjXX> can be converted to implicitly since the subobjXX inherit from obj.

But you can avoid the whole string matching effort by simply declaring create_instance a pure virtual member function of obj and overriding it in each subclass to return std::make_shared<subobjXX>(). With the help of CRTP the repeated definitions in each subclass can even be avoided.

Then you can call it on an object o of type std::shared_ptr<obj> or std::shared_ptr<subclassXX> (assuming the shared_ptr is not empty) simply as o->create_instance() instead of create_instance(o).

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Huh? After `std::shared_ptr o;` there is no object in `o` on which a virtual function could be invoked. – j6t Aug 27 '22 at 07:50
  • I know I can use `std::dynamic_pointer_cast` to convert pointers manually. In fact, `obj` and `subobjxxx` are defined by third-party libraries (I shouldn't modify it). I just want to implement a wrapper to do the pointer conversion automatically, without having to specify the type manually. – J.W Kang Aug 27 '22 at 07:52
  • @j6t I didn't intend that to be a declaration and "after" to mean immediately after that in a list of statements. I just wanted to say what type `o` is supposed to be. I clarified it. – user17732522 Aug 27 '22 at 08:02
  • 1
    @J.WKang I don't understand. You don't need any `dynamic_pointer_cast` or anything. If you don't expect the function to return `std::shared_ptr`, what type would you expect the result of a call like `create_instance(o)` to have? Which of the subclasses is stored in the pointer is a runtime property, but types of expressions need to be determined statically at compile-time. – user17732522 Aug 27 '22 at 08:04