How to declare this without define

How to declare this without define

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <typeinfo>
#include <iostream>
#include <vector>

using namespace std;

#define isIntEx(X) ( isInt( typeid( X ) ) )


bool isInt( const type_info& type ){
    static const vector< const type_info* > range = {&typeid(int), &typeid(long)};

    for( auto it = range.begin(); it != range.end(); ++ it  ){
        if( **it == type ) return true;
    }

    return false;
}

int main()
{

    int p = 5;

    if( isInt( typeid(p) )){
        cout << "YAY" << endl;
    }

    if( isIntEx(p) ){
        cout << "YAY2" << endl;
    }


    return 0;
}


is There any C++ way of doing this..
sorry I am just new with typeid
I don't really know much about it ...

Thanks in advance for your help
I am inclined to say that whenever you find yourself using typeid() that there is probably a flaw in your program.

But in any case, templates can do what you want. And the STL has exactly what you need built-in already.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <limits>

template <typename T>
bool isInt( const T& value )
{
    return std::numeric_limits <T> ::is_specialized;
}

int main()
{
    int p = 5;

    if (isInt( p )) std::cout << "YAY\n";
}

It isn't exactly the same as yours -- it will not compile if you try to use it on a non-integer thing. That could be changed too... but again, doing so indicates a design flaw somewhere.

Hope this helps.
I don't think my program is flawed
I am using Box2D library, in which I have to store pointer as void pointer...
I mean the collision detection use callback function

something like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    void PostSolve(b2Contact *contact, const b2ContactImpulse *impulse ){
        
		void *DataA = contact->GetFixtureA()->GetUserData();
        void *DataB = contact->GetFixtureB()->GetUserData();

		if( DataA && DataB ){
			base* bodyA = static_cast<base*>( DataA );
			base* bodyB = static_cast<base*>( DataB );
			
			if( isHero( bodyA ) ){
				// deal with it
			}
			else if( isHero( bodyB ) ){
				// deal with it
			}
		
		}
    }


this "isHero" function and serveral other seems to need typeid
although the template solution works, I think the define is still better

I think about other solution that need to declare
1
2
3
4
class base {
public:
    virtual Type getType() = 0;
}


but it'll become a hassle as the class grew in number



because I have to store everything in a void pointer
I need a God Object which is not very good design either

I just can't come up with a better solution...
Any suggestion is ok...

it's likely that I will change my design to prevent too much coupling and bad design ...
Last edited on
You can think what you want.

If you are going to be static casting things around, you have more issues to deal with than you think.

The proper solution you discount as a hassle. Type awareness comes with properly-overloaded functions, and you can get rid of that big ol' if-else block you are going to need too.

For the hero vs not-the-hero problem, just swap:

1
2
3
4
5
6
7
8
9
void foo( hero, not_the_hero )
{
  ...
}

inline void foo( not_the_hero, hero )
{
  return foo( hero, not_the_hero );
}

Good luck!
> I am using Box2D library, in which I have to store pointer as void pointer...
> because I have to store everything in a void pointer

To be safe, make sure that every address that you pass to that library (as a pointer to void) is the address of a common polymorphic base class sub-object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
struct character // common base class
{
    virtual ~character() {}
};

struct protagonist : character
{
    // ....
};

struct antagonist : character
{
    // ....
};

struct hero : protagonist
{
    // ...
};

struct harlequin : character
{
    // ...
};

struct anti_hero : protagonist
{
    // ...
};

struct villain : antagonist
{
    // ...
};


And then:
1
2
3
4
void foo( hero* tragic_hero )
{
      library_function_to_store_pointer( /* ... */ static_cast<character*>( tragic_hero /* ... */ ) ;
}


When we get the pointer back from this library, restore type information by a static_cast<> to pointer to base class. And then use a dynamic_cast<> to check the actual dynamic type. (Use it if and only if a suitable virtual function can't be written; usually you can.)

1
2
template < typename T > bool is( const character* c )
{ return dynamic_cast< const T* >(c) != nullptr ; }


And then:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void *DataA = contact->GetFixtureA()->GetUserData();

character* bodyA = static_cast<character*>( DataA );

if( is<hero>(bodyA) )
{
    // ....
}

else if( is<anti_hero>(bodyA) )
{
    // ....
}

else if( is<villain>(bodyA) )
{
    // ...
}

else ...


This is somewhat unsafe against programming errors; using the result of the static_cast<> would result in undefined behaviour if the pointer to void was not obtained via a conversion from pointer to the base class. Consider maintaining a lookup table. (You could have the lookup table as a static member of the base class; add an entry in the constructor, and remove it in the destructor). For instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <unordered_set>

struct character // common base class
{
    virtual ~character() { all_characters.erase(this) ; }

    static bool is_character( const void* p )
    { return all_characters.find(p) != all_characters.end() ; }

    protected: character() { all_characters.insert(this) ; }
                      // likewise for other constructors if any

    private: static std::unordered_set< const void* > all_characters ;
};


And then:
1
2
3
4
5
6
7
8
9
10
void *DataA = contact->GetFixtureA()->GetUserData();

if( character::is_character( DataA ) )
{
    character* bodyA = static_cast<character*>( DataA );
     
    // ...
}

else { /* error; not a character */ }
Last edited on
I mention God Object before right ...

There are some object that doesn't need to keep any user information from me
and the pointer is always NULL

that's why I put
 
if( DataA && DataB )

to make sure that both of them have a value

and to make things easier for me ...
I made a god object
so everything can be Casted that class

I understand your code but I don't think it will suit me ....
as it's a strange way of doing things IMO


Topic archived. No new replies allowed.