6

Okay, sample code first; this is my attempt at communicating what it is that I'm trying to do, although it doesn't compile:

#include <iostream>

template <class T>
class Base
{
public:
    virtual void my_callback() = 0;
};

class Derived1
    : public Base<int>
    , public Base<float>
{
public:
    void my_callback<int>()
    {
        cout << "Int callback for Derived1.\n";
    }
    void my_callback<float>()
    {
        cout << "Float callback for Derived\n";
    }
};

class Derived2
    : public Base<int>
    , public Base<float>
{

public:
    void my_callback<int>()
    {
        cout << "Int callback for Derived2.\n";
    }
    void my_callback<float>()
    {
        cout << "Float callback for Derived2\n";
    }

};

int main()
{
    {
        Derived1 d;
        Base<int> * i_p = d;
        Base<float> * i_f = d;

        i_p->my_callback();
        i_f->my_callback();
    }
    {
        Derived2 d;
        Base<int> * i_p = d;
        Base<float> * i_f = d;

        i_p->my_callback();
        i_f->my_callback();
    }

    //Desired output:
    // Int callback for Derived1.
    // Float callback for Derived1
    // Int callback for Derived2.
    // Float callback for Derived2
    system("Pause");
}

So, what I'm trying to do is to make a sort of wrapper class to inherit from that will automatically connect the derived class to various callback lists; it needs to connect a specific instance of the derived class to the list, and I want the "user" to have / get to make the callback functions as part of making the derived class, as you can see.

It seems like this should be able to work, although I may need to use a different syntax. If it can't work, do you have any suggestions?

Pontus Gagge
  • 17,166
  • 1
  • 38
  • 51
Narfanator
  • 5,595
  • 3
  • 39
  • 71

4 Answers4

2

Yes, you can make this work:

#include <iostream>
using namespace std;

template <class T>
class Base
{
public:
  virtual void my_callback() = 0;
};

class Derived1 : public Base<int>, public Base<float>
{
public:
  void Base<int>::my_callback() {
    cout << "Int callback for Derived1.\n";
  }
  void Base<float>::my_callback() {
    cout << "Float callback for Derived\n";
  }
};

class Derived2 : public Base<int>, public Base<float>
{
public:
  void Base<int>::my_callback() {
    cout << "Int callback for Derived2.\n";
  }
  void Base<float>::my_callback() {
    cout << "Float callback for Derived2\n";
  }
};

int main()
{
  {
    Derived1 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
  {
    Derived2 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
}

Output:

Int callback for Derived1.
Float callback for Derived
Int callback for Derived2.
Float callback for Derived2
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    This does not compile (gcc). Your declarations of Derived::my_callback can not work like that. – Frunsi Dec 13 '09 at 20:58
  • This works for me; of note, I am using Visual Studio 2008, which I know has some features that aren't standard. Thanks! – Narfanator Dec 13 '09 at 21:39
  • Yeah, this is a side-effect of support for explicit interface implementation. You'll be okay as long as you can stick with MSVC. – Hans Passant Dec 13 '09 at 21:57
  • 1
    Thanks but it'd prefer to have standard way to do this. Still thinking how to get this done in standard manner. – Viet Jul 27 '12 at 09:00
2

What you want is not possible.

You could add template specializations, though I do not know if this really helps:

template <class T>
class Base {
public:
  virtual void my_callback() = 0;
};

template <>
class Base<int> {
public:
  virtual void my_callback() {
    cout << "Base<int>::my_callback()\n";
  }
};

template <>
class Base<float> {
public:
  virtual void my_callback() {
    cout << "Base<float>::my_callback()\n";
  }
};

class Derived1 : public Base<int>, public Base<float> {
public:
  // NOTE: no my_callback() implementation here
};

class Derived2 : public Base<int>, public Base<float> {
public:
  virtual void my_callback() {
    cout << "Derived2::my_callback()\n";
  }
};


int main()
{
  {
    Derived1 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
  {
    Derived2 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
}

Output:

Base<int>::my_callback()
Base<float>::my_callback()
Derived2::my_callback()
Derived2::my_callback()

Let me try to explain why:

Derived1 d;
Base<int> * i_p = &d;
Base<float> * i_f = &d;

// will check the vtable, and will call
//  either Derived1::my_callback
//  OR Base<int>::my_callback
i_p->my_callback();

// will check the vtable, and will call
//  either Derived1::my_callback
//  OR Base<float>::my_callback
i_f->my_callback();

Though through the vtable there are two versions of my_callback() in class Derived1, you CAN NOT override either of them, you can only override both at once (like Derived2 does in the example)!

You should just provide two methods "my_callback1()" and "my_callback2()".

Frunsi
  • 7,099
  • 5
  • 36
  • 42
0

Whether using a template class or a non-template one, this can be done by using helper classes in this style or this one.

(It seems this is the only portable solution if you do not plan to use Microsoft specific qualified names.)

Community
  • 1
  • 1
Masood Khaari
  • 2,911
  • 2
  • 23
  • 40
-1

Doesn't virtuality associated with template raises an alarm in your head ? ;)

You have to choose your side, either the static, or the dynamic one.

NewbiZ
  • 2,395
  • 2
  • 26
  • 40