Determine object type by number - c++

I have a class with many derived types, and I have a unique number associated with each derived class. Is there a simple way to match a number with a derived type?
Some pseudo code:
class foo{
public:
virtual int bar(int) = 0;
}
class fan:foo{
public:
int bar(int num){ return num * 5; )
}
class fawn:foo{
public:
int bar(int num){ return num * 9; );
}
int main(){
vector<foo*> obj;
for( int i = 0; i < 100; i ++ ){
int num = rand() % 2;
if( num == 0 )
obj.push_back( new fan() );
if( num == 1 )
obj.push_back( new fawn() );
}
}
This does what I want, but I have many more than two classes, and I plan to add many more. Is there any way to do this in a less verbose manner?
I'm using MinGW, if it matters at all.

What you probably want is the factory pattern. Basically, you'll make something like this:
class foo
{
...
static foo* Create(int num);
}
foo* foo::Create(int num)
{
foo* instance;
switch (num)
{
case 0:
instance = new fan();
break;
case 1:
instance = new fawn();
break;
...
}
return instance;
}
There is no way to get rid of the enumeration, but at least this way you'll have to construct it exactly once and then you can use it everywhere foo is visible.
Edit: Personally I like the above style but a more compact version is
foo* foo::Create(int num)
{
if (num==0) return new fan();
if (num==1) return new fawn();
...
}

You can create an enum for unique identifiers for your derived types.
Then you can just have a field within your derived classes containing this enum, which you set in their respective constructors. That way you can just have a single function to retrieve its type.

Related

Conditionally define, during runtime, which of 3 classes will be used in the rest of C++ code

Here is what I am trying to do in C++. From an external library that I use I have 3 classes, MyClass1, MyClass2 and MyClass3 that are identical in their public functions. I would like to decide, at the beginning of runtime, which one will be used by in the rest of my code depending on the hardware configuraion of the user.
To better illustrate what I mean, let me give an example that I know does not work. If it were possible to conditionally define a typedef at runtime, what I am trying to achieve would look as follows:
const int x = GetX(); //where GetX() is any function that calculates the value of x
typedef std::conditional<x > 0, MyClass1,
std::conditional< x < 0, MyClass2,
MyClass3>::type>::type TheClass;
So that in the rest of the code I would only refer to TheClass, in such a way that it does not matter whether it is aliasing MyClass1, MyClass2 or MyClass3.
However, of course the code above does not work because when x has its value calculated from a function executed at the beginning of runtime, then std::conditional complains that x is not a constant. Which makes sense since typedef cannot be defined at runtime.
So, my question: is there a way to achieve what I am trying to do (not with typedef since I know it cannot be defined at runtime)? Remember that MyClass1, MyClass2 and MyClass3 are externally given by a library, and in such a way that I cannot easily alter them.
The only solution I can see is to use templates to generate the code for you. Modulo syntax errors, your std::conditional based solution does work provided you turn x into a compiler-known value. The trick is to wrap all of the code that uses the typedef in a template function/class that has the integer as a template parameter, as in:
template <int x>
void myMain(){
using TheClass = typename std::conditional<x == 0, MyClass1, MyClass2>::type;
Then you want to make sure that you compile all of the variants (0 and non-zero in my example) and to do so you explicitly call both myMain<0>() and, say, myMain<1>(), as in:
if(x == 0){
myMain<0>();
}
else{
myMain<1>();
}
Now you've turned the condition into something that's evaluated at run-time, but you have the code for both cases compiled and you can execute each (or both) of them to your heart content.
This has the drawback of making whatever uses the class into a template or something that is called by a template. Beyond the "dispatching" point, I would advise to be template on the type rather than on the integer (see the function doSomethingWithClass in the example); this better expresses the fact that your code can work with all of the types you're going to instantiate it with. If you want to make sure that you can only instantiate the functions with the three classes you are interested in, you should consider using the CRTP pattern (curiously recurring template parameter).
On the other hand, this has the advantage (with respect to the other answer based on polymorphism) that you can use the stack rather than the heap.
You can find a working example here.
Hope it helps.
To do this at compile time, the GetX function must be constexpr.
Using the comparison operators also conflicts with the template syntax. You will need to provide consexpr functions for less than and greater than:
constexpr int GetX(){ return 0;}
constexpr bool IsGreater(int x, int y) { return x > y;}
constexpr bool IsLess(int x, int y) { return x < y;}
typedef std::conditional<IsGreater(GetX(),0), MyClass1,
std::conditional<IsLess(GetX(),0), MyClass2,
MyClass3>::type>::type TheClass;
If you can't make GetX() constexpr (because the value is decided at runtime),
then you are looking for a Sum Type. They are quite common in functional programming languages and C++ now has library support in the form of std::variant.
Your example code could be turned into the following:
int main(){
//a type that can be 1 of 3 other types
std::variant<MyClass1,MyClass2,MyClass3> TheClass;
//decide what type it should be at runtime.
const int x = GetX();
if (x > 0) { TheClass = MyClass1(); }
else if (x < 0) { TheClass = MyClass2(); }
else { TheClass = MyClass3(); }
}
Here, you are deciding the type at runtime.
You can go on to use pattern matching for evaluating what type is held.
If all three inherit from a common class you can do this:
class BaseClass
{
virtual int GetSomething() = 0;
};
class Class1 : public BaseClass
{
virtual int GetSomething() override
{
return 1;
}
};
class Class2 : public BaseClass
{
virtual int GetSomething() override
{
return 2;
}
};
class TheClass : public BaseClass
{
virtual int GetSomething() override
{
return 3;
}
};
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1(); }
elseif (x < 0) { classInterface = new MyClass2(); }
else { classInterface = new TheClass(); }
printf(classInterface->GetSometing());
If not, you'll need to wrap them and do something like this:
class Class1
{
int GetSomething()
{
return 1;
}
};
class Class2
{
int GetSomething()
{
return 2;
}
};
class TheClass
{
int GetSomething()
{
return 3;
}
};
class BaseClass
{
virtual int GetSomething() = 0;
};
class Class1Wrapper : public BaseClass
{
Class1 m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
class Class2Wrapper : public BaseClass
{
Class2 m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
class TheClassWrapper : public BaseClass
{
TheClass m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1Wrapper(); }
elseif (x < 0) { classInterface = new MyClass2Wrapper(); }
else { classInterface = new TheClassWrapper(); }
printf(classInterface->GetSometing());
[Edit] ..if you want to save re-doing the if statements you could make a static method to generate a new baseclass:
static BaseClass* GetClass()
{
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1Wrapper(); }
elseif (x < 0) { classInterface = new MyClass2Wrapper; }
else { classInterface = new TheClassWrapper; }
return classInterface;
}
..then call it like this:
BaseClass* classInterface = GetClass();
// Do something
delete classInterface;

How to avoid typeid with better abstraction?

I am using typeid in my code, but it seems to me that the code can be cleaner if I avoid typeid.
If we want to store the type of the class, why would we choose an object-oriented language in the first place?
But I see this pattern over and over again and I do not know how to avoid it.
So I am thinking if this code can be written cleaner with a better abstraction?
Here is the code:
class A {
public:
string type;
};
template <typename T>
class B : public A {
public:
B() {
type = typeid(T).name();
}
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->type == el->type) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
int main(int argc, char **argv) {
Registry reg;
A * b_int1 = new B<int>();
A * b_int2 = new B<int>();
A * b_float = new B<float>();
reg.append(b_int1);
reg.append(b_int2);
reg.append(b_float);
cout << reg.size() << endl;
return 0;
}
The output is 2. (which is the expected result)
Basically we do not want to store two object of the same type in a list.
If you don't want visitors, but you'd like a quick RTTI, I'd suggest looking into this paper: http://www.stroustrup.com/fast_dynamic_casting.pdf
The idea is:
Each class is assigned a distinct prime number for it's own type (e.g., A::my_type = 2; B::my_type = 3)
Then each class is additionally assigned the product of its type and base class values if any (e.g., A::can_cast = A::my_type; B::can_cast = B::my_type * A::can_cast; )
This solves the is_same_dynamic(), is_base_dynamic() problems elegantly: former becomes ==, latter becomes %.
To check whether or not an object belongs to a class derived from a given class, one might use the dynamic_cast<T*> and compare the result with nullptr. Unfortunately, given that we need to check this fact to the unknown type, we are forced to implement such comparison method once per each descendant of class A, but this may be simplified using #define.
Summing up, I would probably write it like this:
#define TYPE_COMPARISON \
virtual bool compare(A* rhs) \
{ \
return dynamic_cast<decltype(this)>(rhs) != nullptr; \
}
class A {
public:
TYPE_COMPARISON
};
template <typename T>
class B : public A {
public:
TYPE_COMPARISON
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->compare(el) && el->compare(a)) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
Also, such method allows you to define whether or not a particular descendant class should be treated as being distinct with its parent.

How to limit class object in C++ [duplicate]

Given a class, I would like to limit the number of objects created from this class to a given number, say 4.
Is there a method to achieve this?
The basic idea is to count the number of created instances in some static variable. I would implement it like this. Simpler approaches exist, but this one has some advantages.
template<class T, int maxInstances>
class Counter {
protected:
Counter() {
if( ++noInstances() > maxInstances ) {
throw logic_error( "Cannot create another instance" );
}
}
int& noInstances() {
static int noInstances = 0;
return noInstances;
}
/* this can be uncommented to restrict the number of instances at given moment rather than creations
~Counter() {
--noInstances();
}
*/
};
class YourClass : Counter<YourClass, 4> {
}
You're looking for the instance manager pattern. Basically what you do is restrict instantiations of that class to a manager class.
class A
{
private: //redundant
friend class AManager;
A();
};
class AManager
{
static int noInstances; //initialize to 0
public:
A* createA()
{
if ( noInstances < 4 )
{
++noInstances;
return new A;
}
return NULL; //or throw exception
}
};
A shorter way is throwing an exception from the constructor, but that can be hard to get right:
class A
{
public:
A()
{
static int count = 0;
++count;
if ( count >= 4 )
{
throw TooManyInstances();
}
}
};

C++ copying data from an abstract base class pointer?

Let's say you have this:
class foo {
public:
virtual int myFunc() = 0;
///...
virtual bool who() = 0; // don't want to implement this
};
class bar : public foo {
public:
int myFunc() {return 3;}
//...
bool who() {return true;} // don't want to implement this
};
class clam : public foo {
public:
int myFunc() {return 4;}
//...
bool who() {return false;} // don't want to implement this
};
int main() {
std::vector<foo*> vec (2, NULL);
vec[0] = new bar();
vec[1] = new clam();
// copy vec and allocate new ptrs as copies of the data pointed to by vec[i]
std::vector<foo*> vec2 (vec.size(), NULL);
for ( int i=0; i<vec.size(); ++i ) {
// obviously not valid expression, but it would be nice if it were this easy
//vec2[i] = new foo(*vec[i]);
// the hard way of copying... is there easier way?
if (vec[i]->who()) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
}
return 0;
}
What I want is some simple way of having the compiler look up in its bookkeeping and allocating/copying vec2[i] according to the stored type of *vec[i]. The workaround is to just make a virtual function which basically returns a value specifying what type *vec[i] is, then doing a conditional allocation based on that.
A common approach goes like this:
class foo {
public:
virtual foo* clone() = 0;
};
class bar : public foo {
public:
virtual bar* clone() { return new bar(*this); }
};
class clam : public foo {
public:
virtual clam* clone() { return new clam(*this); }
};
One way you can do it is by using a dynamic cast to determine type of an object such as done here (Finding the type of an object in C++). but the easiest way would probably be to use typeid.
(assuming you want to maintain your way of using type as a determiner, otherwise I would recommend Joachim's or Igor's as better alternatives :) )
you can use the dynamic_cast to downcast and test the type,
bar* pbar = dynamic_cast<bar*>(vec[i])
if (pbar) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
see for more info in dynamic_cast
http://www.cplusplus.com/doc/tutorial/typecasting/

Increment value from void pointer

I'm trying to modify some variables [not necessary from the same class/struct] from keyboard's shortcuts, something like that:
A foo struct containing variables:
struct Foo {
int a;
float b;
};
struct Foo2 {
int c;
};
And a main like:
int main() {
Foo f;
Foo2 f2
void* p = &(f.a); //it could be &(f2.c)
if ('A' key activated) {
*p += 1;
}
}
Currently, I'm stucked at this point:
error: invalid operands to binary expression ('void' and 'int')
The only way to make it work is to change:
*p += 1;
By:
*(int*)p += 1;
Which is not a good solution, because I should not know the type pointed by p. Is there a way to do that?
Converting the pointer to void* lost the type information and the compiler will not know how to increment. Why don't you make a pointer to Foo instead?
int main() {
Foo f;
Foo* p = &f;
if ('A' key activated) {
p->a += 1;
}
}
Also keep in mind that incrementing a float is not a good idea!
For the quesion in the comment of this answer:
struct FooBar
{
int *a;
float *b;
};
int main() {
Foo f;
Bar b;
FooBar fb{&f.a, &b.b};
if ('A' key activated) {
*(fb.a) += 1;
}
}
Note that this solution is rather C-style. Look at lethal-guitar's answer for a more C++-style solution.
Edit: At first I didn't realize that you want to have different types per entry. Based on the task of handling keyboard shortcuts, you could use a polymorphic class, and put instances of it into a std::map:
class KeyHandler {
public:
virtual void onKeyStroke() = 0;
};
class MyHandler : public KeyHandler {
public:
MyHandler(int& value) : myValue(value) {}
virtual void onKeyStroke() {
myValue_ += 1;
}
private:
int& myValue_; // Other subclasses could have other data
};
// Now place instances of different Handlers into a std::map
typedef std::shared_ptr<KeyHandler> PKeyHandler;
std::map<char, PKeyHandler> bindings;
bindings['A'] = PKeyHandler(new IncrementIntHandler(&someInt));
bindings['B'] = PKeyHandler(new IncrementFloatHandler(&someFloat));
// The actual input handler then just invokes
// the correct handler for a key stroke.
bindings[keyCode]->onKeyStroke();
That way, you can define a handler class for every action you want to support, and implement the corresponding logic into these classes. You could make the base class' implementation just do nothing to handle non-mapped keys, etc.
Sure, use an int pointer instead:
int * p = &f.a;
if ( /* condition */ ) { ++*p; }