I have the following problem which I guess I am solving incorrectly given the problem I am facing:

I have an interface `I` and implementations `A, B, C...` I want to somehow express that I can get some results from couples (f(A, A), f(B, B), f(C, C)) and so on. In other words, I want to interface I to express that 2 identical implementations can be combined to produce some results, while others can be not (you can't get any valid result from f(A, B)).

Right now I have the following:

```
#include <iostream>

using namespace std;
class A;
class B;
class I{
public:
  virtual int f (const I &other) const = 0;
  virtual int fSpecific (const A &other) const { throw runtime_error(""); };
  virtual int fSpecific (const B &other) const { throw runtime_error(""); };
};

class A: public I{

public:
 A(int a) : a(a) {} 
 int f (const I &other) const override { other.fSpecific(*this); }
 int fSpecific (const A &other) const override { /*logic here*/ return a + other.a; }
 int a;
};

class B: public I{

public:
 B(int b1, int b2) : b1(b1), b2(b2) {}
 int f (const I &other) const override { other.fSpecific(*this); }
 int fSpecific (const B &other) const override { /*logic here*/ return b1*b1 + b2*b2 + other.b1*other.b1 + other.b2*other.b2; }
private:
 int b1;
 int b2;
};

int f(const I &a, const I &b) {
    a.f(b);
}

int main()
{
    cout << f(A(1), A(2)) << std::endl; // prints 3
    cout << f(B(1, 2), B(3, 4)) << std::endl; // prints 30
    cout << f(A(1), B(3, 4)) << std::endl; // throws an error

    return 0;
}
/*and so on*/

```

But I guess I use a wrong architecture. as adding classes results in changing `I`. Are there any better solution to express this such a relation?