0

The crux of the issue is I want to create a vector of base pointers to reference children objects. However I'm having issues accessing the methods of the children. I've seen examples of downcasting online but I don't feel it's the best thing for me since I want to keep my code generic. Please look below for a sample of what I'm trying to accomplish.

class Base
{
public:
    stuffx;
private:
    stuffy;
}

template<typename U>
class Child : public Base
{
public:
    Child(
          std::function<U()> getterFunc,
          std::function<void(U)> setterFunc
          ):
          mgetter(getterFunc),
          msetter(setterFunc)
    {
    }
    U getFunction() const {return m_getter();}
    void setFunction(U input) const {return m_setter(input);}

private:

    observableValues() {}
    std::function<U()> m_getter;
    std::function<void(U)> m_setter;
}

int main()
{
    std::vector<std::shared_ptr<Base>> Dummy = {std::make_shared<Child<int>> (std::bind(..),     std::bind(...)),
                                                std::make_shared<Child<string>> (std::bind(..),     std::bind(...)) };
    Dummy.at(0)->getGFunction(); // this throws an error as out of scope.
    (dynamic_cast<Child<int>>(Dummy.at(0))->getGFunction(); // this is ok
}

In this example above my vector is of size 2 which is manageable but my goal is to serialize c++ classes to a psql server and may have to handle vectors of size 30+. My next question is is there a way to automate this in a for loop taking into the account the type deduction that may need to be performed for typename U.

int main()
{
    std::vector<std::shared_ptr<Base>> Dummy = {std::make_shared<Child<int>> (std::bind(..),     std::bind(...)),
                                                std::make_shared<Child<string>> (std::bind(..),     std::bind(...)) };
     std::vector<std::shared_ptr<Base>>::const_iterator it_base = Dummy.begin();
     for (; it_base != Dummy.end(); ++it_base)
     {
         //insert method here for downcasting
     }
}
hdamlaj
  • 51
  • 4
  • Sounds like you're building your own virtual table by hand and looking for a way to index it at compile time by name? If so, why not, you know, use a _virtual table_? IOW, please explain why a normal abstract class wouldn't solve your problem in idiomatic and efficient C++? – davidbak Mar 30 '21 at 23:00
  • Assume for the sake of argument that you managed to downcast the way you want; that inside the loop you have `auto child = magic_downcast(*it_base);` What next? How do you plan to use this `child` pointer? – Igor Tandetnik Mar 31 '21 at 13:16
  • @IgorTandetnik I would use the binds that are imposed on the derived class. `child->getFunction()` and `child->setFunction()` these are bound to the public accessors of other model classes. I need the bind to serialize these classes to a PSQL server. The only solution i've found for the magic_downcast you're referring to, is to do a typeid comparison but I hate my own guts for doing so... :( – hdamlaj Mar 31 '21 at 14:51
  • After calling `getFunction()`, what do you plan to do with its return value (whose type you don't know)? For `setFunction()`, how would you pass an argument to it (whose type you don't know)? Can you show a somewhat realistic use case - again, assuming that the downcast problem is solved by some magic? – Igor Tandetnik Apr 01 '21 at 04:22
  • @IgorTandetnik I have code that's already working using typeid comparisions for downcasting. But the purpose is to use QSqlTableModel (Qt4) -> record -> setValue (type Qvariant) that takes any type you feed it... – hdamlaj Apr 01 '21 at 13:58
  • Add abstract methods `QVariant get();` and `void set(QVariant)` to `Base`, have `Child` override them. – Igor Tandetnik Apr 01 '21 at 22:18

0 Answers0