10

I have a small question: how do I find out what type a C++ pointer is?

I often use a small function in my console programs to gather input, which looks something like this:

void query(string what-to-ask, [insert datatype here] * input)

I would like to create a generic form, using a void pointer, but I can't cin a void pointer, so how to I find out it's type so I can cast it?

sth
  • 222,467
  • 53
  • 283
  • 367
new123456
  • 873
  • 1
  • 12
  • 21
  • 12
    You cast it and cross your fingers. – Ed S. Nov 11 '09 at 22:13
  • Look at how the native C function `scanf()` handles it. – Chris Lutz Nov 11 '09 at 22:22
  • One question: do you want the user to be able to type in ANYTHING and then you want to parse it accordingly? Let's say he types 14, then you want an "int", or 15.4 you want a float? That's it? – Bruno Reis Nov 11 '09 at 22:22
  • Bruno, no , I want to PASS any datatype to it, then the user will enter the datatype I've entered. Like a template, which I guess is my best solution. – new123456 Nov 12 '09 at 12:02

7 Answers7

13

You can't.

However, one alternative is to do away with void pointers, make everything derive from a common base class and use RTTI.

An example:

class Base
{
public:
   virtual ~Base() {}
};

class Foo : public Base { /* ... */ };

void SomeFunction(Base *obj)
{
    Foo *p = dynamic_cast<Foo*>(obj);
    if (p)
    {
        // This is of type Foo, do something with it...
    }
}
asveikau
  • 39,039
  • 2
  • 53
  • 68
6

Instead of passing a void* around that you then need to cast to the correct type you should probably use a template function that can be used with all types you want to read.

This way you get type-safe code and don't have to way to write special code for most input types:

template<typename T>
void query(const string &whattoask, T &input) {
  cout << whattoask << endl;
  cin >> input;
  cout << endl;
}

int main() {
  int i;
  double d;
  string s;

  query("An integer: ", i);
  query("Floating point: ", d);
  query("A word: ", s);
}
sth
  • 222,467
  • 53
  • 283
  • 367
2

void* is the form all data have. You can't "determine" it -- it is it, any data you have in program are void*! Yes, they are raw chunks of memory, by design.

You could program whole your code with use of void* only. Luckily, C language provides additional convenience to you, letting you manipulate some data as is they were not void*. But if you're going to use this convenience, you should not cast them to void* and forget about what type they were.

P Shved
  • 96,026
  • 17
  • 121
  • 165
  • All POINTERS are void*. Last time I checked, a char is not void*. An int might not be void*. A float is not void*. But char*, int* and float* are. – luiscubal Nov 11 '09 at 22:57
  • 1
    His point is that all data is nothing but bytes in memory. Ints, chars, strings, etc. are just interpretations. – Charles Salvia Nov 11 '09 at 23:21
2

Your question is not at all clear to me, but perhaps what you want is to overload query

void query(string what2ask, int* input) {
   cout << what2ask;
   cin >> *input;
}


void query(string what2ask, float* input) {
   cout << what2ask;
   cin >> *input;
}

int age;
float sqrt2;
query("How old are you?", &age);
query("What's the square root of 2?", &sqrt2);
Grumdrig
  • 16,588
  • 14
  • 58
  • 69
1

If you control the datatype yourself, I would probably make a class/struct that contains an enum of all of the data types you care about and pass that. You could then query the passed in pointer for it's datatype, and then cast appropriately.

IE ( pseudo code warning - treating this as a struct for now. )

class MyDataType {
     enum aDataType type;
     void * myData;
}

void query( string whatToAsk, MyDataType * pdata)
{
    switch ( pdata.type) {
        case integer:
              int * workInt = (int * )  pdata;
              do whatever you want to to get the data
              break;
        case someFunkyObject:
              someFunkyObject pob = (SomeFunkyObject *) pdata;
              Do whatever you want with the data.

        etc.
    }
}
  • 1
    If I were tagging with enums (rather than using RTTI), I would be more inclined to make "myData" a union instead of a void *... Fewer pointers that way, and no double-indirection. Although it's much more C style than C++. – asveikau Nov 11 '09 at 22:34
0

If I understand what you're asking then the usual way to do this is to create an interface class that supports query(string what-to-ask) and then instead of using a void pointer just pass a pointer to the interface. Then you can call query() on that instance.

Aaron
  • 9,123
  • 5
  • 40
  • 38
0

Nope. You can't do this. If you need something like this, I suggest Boost.Any.

rlbond
  • 65,341
  • 56
  • 178
  • 228