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.
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.
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)
Related
I have a base class in which I define an array of structs (of base types) and some methods that act on its objects; I never instantiate directly this class, just created varius sublasses of it. Now, in each subclass I would like to redefine the array size to the subclass particular needs.
Consider that I would like to avoid dynamic allocation in order to keep the program more dependable and because I like to see at compile time the amount of memory I'm using with my design.
I tryed by simply redefining the array in the subclasses; the compiler (I use Arduino IDE) does not complain about it but, from the amount of memory used reported by the compiler, I see that actually both arrays exist (the one defined in base class and the one "redefined" in the subclass) so it seems this is not the way to do it.
I found a suggestion about using templates but It hasn't received much approval, and because I read that templates are about making a class manage different data types, I think my problem of wanting just a different array size could have a more simple solution.
What is the correct way to obtain what I want?
Here is an example of my (wrong) code:
typedef struct {
char val1;
int val2;
} DataItem;
class BaseClass {
DataItem dataItems[5];
};
class Sublass_A : public BaseClass {
DataItem dataItems[50];
};
class Sublass_B : public BaseClass {
DataItem dataItems[15];
};
With template, you might do something like:
template <std::size_t N>
class ItemsArray {
DataItem dataItems[N];
};
using classA = ItemsArray<50>;
using classA = ItemsArray<15>;
Here is the initial code of my question, corrected following the #Jarod42's answer.
typedef struct {
char val1;
int val2;
} DataItem;
template <size_t N = 5> // 5 is the default value if the size is not specified
class BaseClass {
DataItem dataItems[N];
};
class Sublass_A : public BaseClass<50> {
};
class Sublass_B : public BaseClass<15> {
};
It compiles correctly and tests using sizeof() on the subclasses objects reported the expected sizes of the array.
My question is similar to: Can't use macro define class in C++, but is a little more complicated:
class ABC
{
public:
DECLARATION(ABC)
private:
void ABCFun1();
void ABCFun2();
// ... and so on
}
#define DECLARATION(TYPE)\
std::string GetClassName()\
{\
return std::string(#TYPE);
}\
// the macro can goes on to declare more
// common interfaces, like Initialize(), ...etc.
So, the point is, I can use this macro to generate other classes like DEF, GHI...etc,
where all of them shares the common part of DECLARATION, but also having their own private
parts.
If there isn't the need of GetClassName(), which seems can only be implemented using macro #,
then I can use inheritance to put them together.
Or, if there aren't the private things, I can use template.
So, with these 2 things mixed up, is there any way to avoid the macro?
Thanks!
You can us the CTRP to generate some functions. But remember that names won't be available unless you use macros (that will change when compile-time reflection will be made into the standard, maybe for C++17).
CRTP:
template<typename T>
class Base
{
public:
void myFunc()
{
((T*)this)->functionA();
((T*)this)->functionB();
// ...
}
};
class ABC : public Base<ABC>
{
// ...
};
Edit: BЈовић answer is right, but some comments about RTTI:
it is not portable
typeid(T).name() is implementation dependant (it can return "" for every type if an implementor wanted to)
it is slow.
See this question about RTTI and LLVM, for example (or this one about performance).
To store strings, you should use the preprocessor as for now. Note that it does not work with templated parameters (ie, if you have template<typename T>, then #T will expand to "T", not the actual typename).
Then, there is a technique that allows to pass a string to a template parameter (sort-of):
#define NAME( _n_ , _t_ ) \
struct _t_ \
{ \
static const char* asName() \
{ \
return #_n_; \
} \
}
It changes the string to a type. The string in itself is a litteral, so it is put straight into the executable (and is read-only, attempts to modify it will most likely result in a crash).
I use this in the SPARK Particle Engine, for example, where I implemented a reflection module.
As far as I can see from the vague "the macro goes on..." comment, the DECLARATION macro seems to do one or several of these things:
define members are independent of ABC
define members (methods or data members) that depend on the type ABC
define members that use the string "ABC"
tl;dr: #1 is trivial, as you noted in the question. #2 is relatively easy, use CRTP, #3 is not satisfactorily doable without a macro.
update:
In the comments below you mention that you want a guarantee that the string and the class name be "sync-ed". This is definitely impossible without macros in current C++. (see "update" below)
The first is easy to achieve without a macro - just inherit from a ordinary base class that defines the members.
The second can be done relatively easy too, via a CRTP: create a template class that takes the type as parameter and inherit from the template, instantiated with the type itself:
template <class T>
class Base {
public:
void doSomething(T const&);
};
class ABC : public Base<ABC> {
// inherited void doSomething(ABC const&);
};
The third one is tricky and not easily solvable without at least a bit of boilerplate.
C++ has no features apart from macros that convert a name (class name, function name, variable name...) into a string representing that name. (such language features are part of a family of features commonly called reflection). An exception is typeid(T).name(), nut the outcome is not standardized, so it may or may not give you the name of the class, something different, readable or unreadable or just an empty string.
So, to (portably and realiably) get a string "ABC" for a class ABC you have to write "ABC" at least once in addition to the class definition. That's not so bad yet, you have to do something similar for #2 as well, as it seems impossible to use the type of ABC without explicitly mentioning ABC again.
Update: Since you have to explicitly type both the string and the class name, there can be no guarantee that both are always the same, except with a macro. Even the macro you have in the question is prone to changes/typos:
class ABC {
DECLARATION(ACB);
};
This will give a wrong class name if the macro only provides the stringified version of it's argument without doing something with the type (in that case the compiler would tell you that ACB is no type). If you want the guarantee, use one macro that does everything, including the class definition:
#define CLASS_DEF(x) \
class x##_base { \
std::string GetClassName() { \
return std::string(#x); \
} \
}; \
class x : public x##_base
and then later:
CLASS_DEF(ABC)
{
private:
void ABCFun1();
void ABCFun2();
// ... and so on
}
Putting it in a base class makes it possible to write the macro and then just a normal class body.
So what can we do for #3 without a macro, if we don't need the sync-guarantee?
providing the string as a template parameter to some base class would be the nicest way but is, in short, not possible. This article covers strings as template parameters and has to fall back to macros in the end. The closest we can get is some form of the boost::mpl::string<'Hell','o Wo','rld!'> mentioned in the article. The length would be limited by some arbitrary definition, if C++11 variadic templates are not available, and the definition of the base class (or boost::mpl::string) would probably use a good deal of macro magic itself, but at least you are rid of self-defined macros in the class itself. Something that uses #2 and #3 would have to look somewhat like (i make the name longer to demonstate the restrictions of the approach)
class ABCDE: public Base<ABCDE, 'ABCD', 'E'> { /* ... */ }
having the string as a static data member constant with a predefined name. This is an option that fits well together with CRTP, if you have to use it anyways:
template <class T>
class Base {
public:
std::string GetClassName() const {
return T::name;
};
};
class ABC : public Base<ABC> {
public:
constexpr static char const * name = "ABC";
};
In C++03, you would have to use a static const member that has to be defined outside the class definition (i.e. in ABC.cpp)
having the string as a nonstatic data member of ABC works similarly:
template <class T>
class Base {
public:
std::string GetClassName() const {
return static_cast<T const*>(this)->name;
};
};
class ABC : public Base<ABC> {
public:
const std::string name = "ABC";
};
This requires C++11 for the in-class member initialization. In C++03 the name has to be properly initialized in every constructor.
having the string as data member of the base class works and should be preferred imo, if you don't have type-dependent members, i.e. if you don't need CRTP to do #2:
class Base {
public:
Base(std::string nm) : name(nm) {}
std::string GetClassName() const {
return name;
};
std::string name;
};
class ABC : public Base {
public:
ABC() : Base("ABC") {}
ABC(int i) : ABC() { /*another ctor*/ }
};
To do the initialization of Base with the class name just once you can use the C++11 delegating constructors, although it's not much different writing Base("ABC") or ABC() in each initializer list.
If you just need to get the type's name, you can use typeinfo::name() method.
You could use CRTP, which contains everything that you need. Something like this :
template< typename T >
class MyBase
{
public:
MyBase() : className( typeid(T).name() ){}
virtual ~MyBase(){}
std::string className;
// common interfaces, like Initialize()
};
then use it :
class A : public MyBase<A>
{
};
In VS, when you type "class." you are presented with a list of functions you can call. Having to look through a list of 15-20 functions, half or more of which being members is not nice.
I'm extremely interested in finding a system that will hide private member functions or move them to the end of the list, so the user doesn't have to scroll through a list of locked functions.
I have four design types:
1) Namespace method hiding
2) Class based method hiding
3) pimpl version
4) _ prefix
Here is the code for clarity:
#pragma once
#include <memory>
using namespace std; // ignore the fact this is global here
struct Hide_Test_Data
{
int value;
};
namespace Hide_Test_Private_Member_Ns
{
void private_function(Hide_Test_Data& data) {}
};
class Hide_Test_Methods
{
public:
Hide_Test_Methods() {}
void private_function(Hide_Test_Data& data) {}
};
class Hide_Test_Methods_Alt
{
public:
Hide_Test_Methods_Alt() {}
void private_function() {}
private:
Hide_Test_Data htd_;
};
class Hide_Test
{
public:
Hide_Test() {}
void public_function()
{
_private_function(); // member function prefixed with _
Hide_Test_Private_Member_Ns::private_function(htd_); // namespace version
htm_.private_function(htd_); // subclass version (no private data)
pimpl->private_function(); // pimpl version (with private data)
}
private:
Hide_Test_Data htd_; // class to hold data
Hide_Test_Methods htm_; // class to hold methods
void _private_function() {}; // _ prefixed member function
unique_ptr<Hide_Test_Methods_Alt> pimpl;
};
Note:
The unique_ptr Hide_Test_Methods_Alt version has member data which the standard one doesn't. Both could be implemented in either way.
The _ prefix doesn't hide the member data, but it does move it to the end of the list. This has the advantage of allowing user to see the private functions if they are interested. My main goal is not to hide the private member functions, just to move them out of the way.
Prefixing data with _ 'should' be safe out of global scope according to the standard as long as it is followed with a lowercase letter.
Which of these designs would be more acceptable in general? I imagine I could work with all four of these design types comfortably, but I would rather hear some input on some of the pros and cons I may not have thought of.
Pimpl uses a pointer to ease copying the member data. In the cases where I don't need to copy the member data, is just using a class better or worse?
I have done some research and found a few related threads in this forum:
Hiding private data members? (C++) - this one points out the pimpl idiom (which I added to my examples above).
How to hide private members of a Class? - talks about VS intellisense not hiding private members
Why does Visual Studio's intellisense show private members and functions? - gives an #ifdef solution that I don't really like the idea of.
I think this question is different enough from the others presented to be worthy posting. Thanks as always.
Generally a pimpl pattern is applied when you want to be able to change implementations at link time and as such must be a pointer
Here you don't want the overhead, so you could consider an inner class and an instance of that class as opposed to a pointer:
class fewfunctions
{
class manyfunctions
{
public:
int a1() { return 0; }
int a2() { return 0; }
int a3() { return 0; }
int a4() { return 0; }
// ... many more
};
public:
int b() { return a.a1() + a.a2() + a.a3() +a.a4(); }
private:
manyfunctions a;
};
Only b will show up as a function (a shows up as locked)
I'm new to C++ and I'm having trouble with this. So I'm trying to make classes that can call on each other's fields using a generic subclass.
Basically, I'm trying to make a game where there is a generic type and three types that have strengths/weaknesses against each other. I only really have experience in Java, and the translation to c++ for this kind of thing isn't clicking for me
Generic type splits into three types: type 1, type 2, type 3.
Generic type needs to be concrete
In the generic type there are fields attack, defense, hitpoints
types 1, 2, and 3 all inherit these fields.
I'm trying to make a virtual function in the generic class:
virtual void attack(Generic* g);
Problem is, when I try to make type_1.attack(generic) for example, I want to do g->hitpoints to get generic's hitpoints, but it just doesn't seem to work like that in C++.
Additionally, I know I must be doing something wrong, because type 1, 2 and 3 all include the generic type's header, but if I want to include those 3 headers in main.cpp, it'll give me an error for declaring generic 3 separate times.
How would I go about doing this?
Sorry this is a very specific question and it's a little bit vague. Please let me know if I need to clarify anything
Edit: Here is the basic setup of what I'm talking about
//in generic.h
class Generic {
protected:
int hitpoints;
int strength;
int defense;
public:
virtual void attack(Generic* g);
};
//type1.h
#include 'generic.h'
class Type1 : public Generic {
void attack (Generic* g);
};
//in type1.cpp
void Type1::attack(Generic*g) {
g->hitpoints = strength - g->defense;
}
An object can access its own protected members that are inherited from a base class. But an object cannot access another object's protected members. That is the difference between private vs protected - private members can only be accessed by the class that declares them, but protected members can be accessed by the declaring class and its descendants. Both are still private to outside code, though.
To do what you are attempting, hitpoints needs to be public.
type 1, 2 and 3 all include the generic type's header, but if I want to include those 3 headers in main.cpp, it'll give me an error for declaring generic 3 separate times.'
You need to make sure that the class is declared only once. This is usually done with guards in the .h file:
//generic.h
#ifndef GENERIC_H
#define GENERIC_H
//all declarations go here
#endif /* GENERIC_H */
When you type #include "generic.h", the C++ processor will basically just paste the contents of foo.h. Since you included it thrice (via the includes for classes Type1, Type2 and Type3, that each include generic.h), the class is delcared three times.
You should do something like this:
// generic.h
#pragma once
class Generic {
protected:
int hitpoints_;
int strength_;
int defense_;
void do_damage(Generic* g, int damage) { g->hitpoints_ -= damage; }
public:
virtual void attack(Generic* g) = 0;
int hitpoints() const { return hitpoints_; }
int strength() const { return strength_; }
int defense() const { return defense_; }
};
// type1.cpp
void Type1::attack(Generic* g) {
do_damage(g, strength_ - g->defense());
}
To avoid your second problem (a class defined multiple times), there is something called include guards (they guard you from including the same file several times). It works like this way:
// File: type1.h
// At the very beginning
#ifndef type1_h
#define type1_h
// Here come the rest of your file and, at the end:
#endif
This way, the contents of the file are only included once, because after that type1_h will be defined, so everything will be skipped. This may be the only use of #define that is universally accepted in C++.
As for your first problem, protected means that derived classes can read that member for themselves or objects of their own class, but nobody else. This includes that derived classes cannot read that member for objects belonging to another class, including the base class itself. I'm afraid you'll have to rethink your design.
The best that you can do is just changing the privacy of the protected members or, even better, provide public accessors and keep the data members private. public data members are seldom a good idea in classes (structs are a different thing):
class Generic {
private:
int hitpoints;
int strength;
int defense;
public:
virtual void attack(Generic* g);
void SetHitpoints(int hp) {hitpoints = hp;}
int GetDefense() {return defense;}
};
The meaning of protected for data members is subtly different from what you might expect. When you have a class A with a protected data member d and a class B that inherits from A (with public inheritance), then B's member functions can access d – but only on objects of type B, not on any object of type A. If that seems confusing, a code example will hopefully make it clearer:
class A {
protected:
int d;
};
class B : public A {
void fine(B& b) { b.d = 0; }
void wrong(A& a) { a.d = 0; }
};
int main() { }
As the names indicate, the assignment in functions fine is ok, but you'll get a compiler error for the one in wrong if you try to compile the code. The best way to deal with this is probably to make the data members private and write protected member functions that operate on them, as in abyss.7's answer.
For the double inclusion problem, use either include guards or #pragma once.
I suspect this is not possible under the current C++ standards but I'll ask anyway.
What I'm trying to achieve is to get the compiler to figure out during compile time if a class contains any member variable of type Base (along with its derivations).
e.g.
struct Base
{
};
struct Derived : public Base
{
};
struct Foo
{
int x;
Derived a;
Derived b;
};
struct Bar
{
int x;
};
I want something along the line of,
has_member_of_type<Base, Foo>::value
in which case would be true (one or more member vars have a base type of Base), while anything else (including fundamental types) would eval to false.
e.g.
has_member_of_type<Base, char>::value = false
has_member_of_type<Base, Bar>::value = false
Note that I'm trying to use has_member_of_type in my library to detect and use different code branch if user class has a member variable of a certain type.
No, it's not possible. You can't even access the members (unless told their names), let alone probe their types.