Multiple inheritance and duck printing

While working on Kira3, I played with the C ++ compiler and was looking for a good way to use Kira printing. I was hoping (as it was for several years of direct programming in C ++) that I could use multiple inheritance to access multiple types of members. Alas, I still haven't done it ...

The ideal code would look like this:

class WithX { public: int x; };
class WithY { public: int y; };
class WithZ { public: int z; };

class Point2D : public WithX, public WithY { };
class Point3D : public WithZ, public WithX, public WithY { };

void ZeroOut(Point2D * p) { p->x = 0; p->y = 0; };

int _tmain(int argc, _TCHAR* argv[])
{
    Point3D* p = new Point3D();
    p->x = 1;
    p->y = 1;
    p->z = 1;
    ZeroOut(p);
    return 0;
}

      

However, it throws an input error when calling ZeroOut (p). This is a very sad face. I can make it work by creating a tower type. In the example above, I could change class Point3D: public WithZ, public WiThanks, public WithY {}; in class Point3D: public Point2D, public WithZ {};

The problem now is that I have structures that overlap. I would either throw an error, which would be a pain to solve in kira's code, or I have a compiler doing something different. I tried

class Point3D : public Point2D, public WithZ, public WithX, public WithY { }; 

      

with the hope of compiler concatenation, but this gives ambiguous access to member variables. This can be fixed by replicating the entries to ambiguous member variables, and this might be a solution in my compilation phase. This solution requires more memory.

Any ideas how to solve this problem without losing memory?

Or, is there a way to dump variables to multiple types? as

(WithX,WithY *)p

      

+2


source to share


3 answers


I've tried ... with the hope of compiler concatenation, but this gives ambiguous access to member variables.



To solve this problem, try virtual inheritance .

+2


source


I don't know anything about Cyrus, but you could solve at least this particular problem with a template function - which is kind of like compiling duck typing.

#include <iostream>
class WithX { public: int x; };
class WithY { public: int y; };
class WithZ { public: int z; };

class Point2D : public WithX, public WithY { };
class Point3D : public WithZ, public WithX, public WithY { };

// As long as we pass in a type that has an x and a y member,
// ZeroOut will compile and run correctly, setting x and y to zero.
template <typename T>  
void ZeroOut(T * p) { p->x = 0; p->y = 0; };

int main(int argc, char* argv[])
{
    Point3D* p = new Point3D();
    p->x = 1;
    p->y = 1;
    p->z = 1;
    ZeroOut(p);
    std::cout << p->x << " " << p->y << " " << p->z << std::endl;
    return 0;
}

      

correctly outputs:

$ ./a.out
0 0 1

You mentioned in a comment that uses more code - I would like to point out that the added code is negligible. I changed the main function to:



int main(int argc, char* argv[])
{
    Point3D* p = new Point3D();
    p->x = 1;
    p->y = 1;
    p->z = 1;
    ZeroOut(p);
#ifdef USE_2D
    Point2D *q = new Point2D();
    q->x = 1;
    q->y = 1;
    ZeroOut(q);
#endif
    std::cout << p->x << " " << p->y << " " << p->z << std::endl;
    return 0;
}

      

and compiling this way gives:

$ g ++ p.cpp -o just3
$ g ++ p.cpp -DUSE_2D -o 3and2
$ wc -c * 3 *
 9949 3and2
 9908 just3
19857 total

Are you really going to split the hair for a 41 byte difference in the executable? Well, if you are, just enable optimization:

$ g ++ -O2 p.cpp -o just3
$ g ++ -O2 p.cpp -DUSE_2D -o 3and2
$ wc -c * 3 *
 9882 3and2
 9882 just3
19764 total
+8


source


Overload error?

void ZeroOut(Point2D * p) { p->x = 0; p->y = 0; };
void ZeroOut(Point3D * p) { /* whatever you want*/ };

      

+3


source







All Articles