templatesc++17static-polymorphism

inserting member function ptr into a map


EDIT delete formatting from code itself (bold).

Edit 2 added the at the end of the answer the fix

I have the following code where I'm trying to create static polymorphism and template classes, I'm trying to insert into a map in Only one of the derived types member function ptr. the definition of the map is this:

std::map<std::string,void(derived::*)()> m_func;

and the insert command is this:

`m_func.insert(make_pair("yaodav",&derived::HelloWorld));`

and this is the whole code:

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <any>
#include <typeinfo>
#include <typeindex>
using namespace std;


template<class Derived>
class base
{
public:
    void clean()
    {
        cout << "I'm cleannig \n";
    }
    void process()
    {
        static_cast<Derived*>(this)->setup();
        static_cast<Derived*>(this)->run();
        static_cast<Derived*>(this)->cleanup();
    }
};


class derived : public  base<derived> 
{
    friend class base<derived>;
    void setup() {
        m_func.insert(make_pair("yaodav",&derived::HelloWorld));
        cout << "derived setup \n"; }
    void run() { cout << "derived run \n"; }
    void cleanup() { cout << "derived cleanup \n"; }
    void HelloWorld() {cout << "hwllo from derived \n"; }
    std::map<std::string,void(derived::*)()> m_func;

};


class derived1 : public base<derived1> 
{
    friend class base<derived1>;
    void setup() {cout << "derived1 setup \n"; }
    void run() { cout << "derived1 run \n"; }
    void cleanup() { cout << "derived1 cleanup \n"; }
    void HelloWorld(){}
};

template <class T>
class Y{
 public:
 std::vector<std::any> m_vec;   

};


template <typename T>
class D:public Y<T>
{
    public:
    friend class Y<T>;
    void print()
    {
        for(auto& e: Y<T>::m_vec)
        {
             if(e.type()==typeid(base<derived1>*))
            {
                try {
                    auto* r = any_cast<base<derived1>*>(e);
                    r->process();
                }
                catch(const std::bad_any_cast& e) {
                    std::cout << e.what() << '\n';
                }
            }
            else
            {
                try {
                    auto *r = any_cast<base<derived> *>(e);
                    r->process();
                }
                catch(const std::bad_any_cast& e) {
                    std::cout << e.what() << '\n';
                }
            }

        }
    } 
};


int main()
{
        base<derived>* b =  new base<derived>;
        base<derived1>* c =  new base<derived1>;

        D<derived> y;
        y.m_vec.push_back(b);
        y.m_vec.push_back(c);
        y.print();
}

but when the insert function called (the bold section) I'm getting a Segmentation fault, it's like the m_func dos not exist when I'm running a debugger and I wont to print m_func I'm getting :

here is no member or method named m_func

why is that happening and how to fix it

The fix

 base<derived>* b =  new derived;
 base<derived1>* c =  new derived1;

instead of

 base<derived>* b =  new base<derived>;
 base<derived1>* c =  new <derived1>;

Solution

  • Your code is roughly equivalent to this:

    base<derived>* b = new base<derived>;
    b->process();
    

    Inside process, there's static_cast<Derived*>(this) - but the instance of base<derived> that b points to is not in fact an instance of derived. You have instantiated base<derived> standalone, not as part of a derived instance. Your program never created an instance of derived, nor derived1. So you are trying to call a member function of an object that never existed, whereupon your program exhibits undefined behavior.


    Even more streamlined version of your code would look like this:

    class Base{};
    class Derived : public Base {
    public:
      void DoSomething() {};
    };
    
    int main() {
      Base* b = new Base;
      static_cast<Derived*>(b)->DoSomethind();  // undefined behavior here
    }
    

    This way, it should be clearer what's wrong.