struct Test1 : public Base {
enum { type = 1 };
int a;
char ch;
virtual void func1();
};
struct Test2 : public Base {
enum { type = 2 };
int a;
char ch;
virtual void func1();
};
I'm developing a project with C 14. For some compatibility reason, I have to declare two classes as above, whose members are exactly the same.
My question is if there is some metaprogramming method, which allows me to check if the two classes have exactly the same members?
real issue
Yeah, I know it's so weird but I did get such an issue...
I'm developing a web server, each class above is a protocol.
Now the problem is that some Android developer has wrongly used the protocol Test1
, so we can't touch it as users may not update their App. What I could do is just add another protocol. So I add the class Test2
.
Since the two protocols do the exactly the samething, I want to make sure that they are always the same. Meaning that if someone adds a member into Test1
someday but he forgets to add the member into Test2
, I want to get a compile-time error.
BTW, I only care about the data member, not member function.
CodePudding user response:
I don't like the premise of this question because it is essentially asks for a way to keep code duplication. However in practice shit happens and if someone wants two classes with the same content the better idea would be not to declare two classes and then check them for compatibility, but to declare them just once. This can be done by using a base class or by using preprocessor. The latter case will also prevent any new members from sneaking into derived classes while adding new members into both classes with require just a single modification:
#define MAKE_CLASS(mp_name) \
struct mp_name : public Base { \
enum { type = 1 }; \
int a; \
char ch; \
void func1(); \
};
MAKE_CLASS(test1)
MAKE_CLASS(test2)
CodePudding user response:
Is it possible to check if two classes have the same members
If you can upgrade to C 20, and if the classes are standard layout, and you aren't concerned about exact matches for types, but rather layout compatibility - such that one class might have a const member while the other has non-const - then you can use the std::is_layout_compatible
type trait.
Otherwise, you may have to resort to meta-programming.
I want to make sure that they are always the same.
Regarding the XY-problem, if you can change Test1
in an API compatible way, then inheritance could be a solution:
struct TestData : Base {
int a;
char ch;
};
template<int type>
struct TestBase : TestData {
enum { type = type };
};
struct Test1 : TestBase<1> {
void func1();
};
struct Test2 : TestBase<2> {
void func1();
};
If you cannot touch Test1
at all, then a hacky workaround would be to use it as a base:
struct Test2 : Test1 {
enum { type = 2 };
void func1();
};
It's not ideal due to the implicit conversions. You could avoid those by using private inheritance, but then you have the problem of shared public non-virtual Base
.