Hello!

I want to use static_cast<int> on a void* member Variable in another class. (class aMessage). aMessage class has a public variable void* pVar. While using static_cast on a local variable is running smoothly, I get a compiler error trying to cast it on the aMessage->pVar.

pVar is being declared in gMessage.
pVar is also being initialized in constructor with
gMessage::gMessage(unsigned short int passedType, std::string passedString):pVar(0){...}

This is the flawed code:

void gFont::AddTest(int passedPosition, std::string passedString, void *passedVar, void *passedVar2)
    {
    gMessage* aMessage =  new gMessage(1, passedString); // Constructor for gMessage, initializing

    int* passedInt=static_cast<int*> (passedVar); // This one works without problem!

    aMessage->pVar=passedInt;

    int* aMessage->pVar=static_cast<int*> (aMessage->pVar); // This one does not work at all (see log beneath)
    }

D:\C++ Projects\Project1\project.cpp||In member function `void gFont::AddTest(int, std::string, void*, void*)':|
D:\C++ Projects\Project1\project.cpp|1918|error: expected initializer before '->' token|

Any help is very appreciated. Thank you!

I figured it, however it is very ugly code.. I decleared in the other class gMessage another pointer to an int and then assign it

void gFont::AddTest(int passedPosition, std::string passedString, void *passedVar, void *passedVar2)
    {
    gMessage* aMessage =  new gMessage(1, passedString);
    int* passedInt=static_cast<int*> (passedVar);
    aMessage->pVar=passedInt;
    int* pInt_loc = static_cast<int*> (aMessage->pVar);
    aMessage->pInt=pInt_loc;
}

It works but I get a funny feeling with it.. ;/

All I want to do is to pass an unknown type of pointer and interpret it the right way and store it in another class member variable..

must be something else wrong because this compiles ok with vc++ 2008 Express

class A
{
public:
    void* ptr;
    A() {ptr = 0;}
};

int main()
{
    A* a = new A;
    int* p = static_cast<int*>(a->ptr);
    *p = 1;
}

This one also has no problems

class A
{
public:
    void* ptr;
    A() {ptr = 0;}
};

class B 
{
public:
    int* ptr;
    B() {ptr = 0;}
};

int main()
{
    A* a = new A;
    B* b = new B;
    b->ptr = static_cast<int*>(a->ptr);
}

I want my member class void* pointer to be change to a int* pointer. This does not however work.

D:\C++ Projects\marc\console\main.cpp||In member function `void B::Do(void*)':|
D:\C++ Projects\marc\console\main.cpp|26|error: `void*' is not a pointer-to-object type|
||=== Build finished: 1 errors, 0 warnings ===|

#include <iostream>

class A;
class B;

class A
    {
    public:
        A():      pVar(0){};
        
        void*     pVar;
    };

class B
    {
    public:
        B(){};
        void      Do(void *passedVar);
    };

void B::Do(void *passedVar)
    {
    A* a = new A;
    a->pVar=static_cast<int*>(passedVar);

    std::cout << *a->pVar; 

// Basically I want to have pVar to be a pointer to 
// an int but obviously it is and remains a void* pointer... ;(
    
    }

int main()
    {
    B* b = new B;
    int*cVar=0;

    b->Do(cVar);
    }

I think it would work if you could change this

a->pVar=static_cast<int*>(passedVar);

to

static_cast<int*>(a->pVar)=static_cast<int*>(passedVar);

The error you get is because you are trying to make a void pointer refer to a int pointer (Because the cast makes the void pointer to passedVar behave like an int*)
So please try that up too.

Cast the void pointer when you want to use it as an int pointer, not when you want to store it as a void pointer:

#include <iostream>

class A;
class B;

class A
    {
    public:
        A():      pVar(0){};
        
        void*     pVar;
    };

class B
    {
    public:
        B(){};
        void      Do(void *passedVar);
    };

void B::Do(void *passedVar)
    {
    A* a = new A;
    a->pVar = passedVar;

    std::cout << *static_cast<int*>(a->pVar) << '\n'; 
    }

int main()
    {
    B* b = new B;
    int value = 123;
    int*cVar=&value;

    b->Do(cVar);
    }

Sky Diploma: Your proposal is not working as I get this->

D:\C++ Projects\marc\console\main.cpp|24|error: ISO C++ forbids cast to non-reference type used as lvalue|

Tom Gunn: Good idea, however, is there a way to change a member void pointer to an int pointer? If this were possible, I wouldnt need to store all kind of pointers as members and assign the passedVar to the correct one. That would be less ugly.

Also, is there a way to know the type of passed pointer? Let's say I pass an int* to Do(void* p). How can I figure out that int* was passed? I thought of checking with size, or having a seperate class stores all addresses and compares it, but is there an easy way to know what type was passed?

is there a way to change a member void pointer to an int pointer?

The member is a void pointer, that will not change unless you change the type in your class definition. The only way to turn the void pointer into an int pointer is to cast it when you need an int pointer, as in my example.

Also, is there a way to know the type of passed pointer? Let's say I pass an int* to Do(void* p). How can I figure out that int* was passed?

You can do it, but not with void pointers unless you want to write a smart pointer class that knows the type. Using templates and RTTI will give you enough information to figure out what type of pointer was passed:

#include <iostream>
#include <typeinfo>
#include <string>

template <typename T>
void function(T* p)
{
    if (typeid(T) != typeid(int))
    {
        std::string actualType = typeid(T).name();
        throw std::invalid_argument(actualType + "* does not match int*");
    }

    std::cout << *(int*)p << '\n';
}

int main() try
{
    int ivalue = 123;
    double dvalue = 123;
    int *pi = &ivalue;
    double *pd = &dvalue;

    function(pi);
    function(pd);
}
catch (std::exception const& e)
{
    std::cerr << e.what() << '\n';
}

But I think you are probably doing something unnecessary. The actual type of a void pointer should be well known or not needed. If you need it, your design needs work. So what are you writing that needs this kind of type check?

You are right I don't need to know it so much, however, only to have more controll over errors and have a quicker way of coding thousand messages ahead. I am doing an opengl application and I need to know the passed type just out of confortability after all since I will have more than 100++ different message to go.

I have a message class which works with font bitmaps and does something like that to get the basic idea:

First I initialize my messagesystem with many different messages:

Font->Init("Arial.tga")

bool InitMessages(void)
{
Message(DISPLAY_MOUSE_COORD, "Those are my coordinates: X %f and Y %f", gMouse->GetX(), gMouse->GetY);
Message(DISPLAY_USERINFO, "User Name %s, Age %d", User.GetName(), User.GetAge());
Message(DISPLAY_SCROLLINFO, "ScrollSpeed: %f", Camera.GetScrollSpeed());
...
..
.
}

The ".." are any string and the %f, %s etc. are being replaced by the value, similar to <iostream>, only that this works now completely in OpenGL.

Then within the code I can I call the right message with

if (Button(G) && Event(WHATEVER)) DisplayMessage->OnScreen(DISPLAY_USERINFO, Line 12, Colum 14);

which will print on an OpenGL Screen at the given coordinates:

Jack Bauer, Age 43

or

if (MousePress(LEFT)) DisplayMessage->OnScrolldisplay(DISPLAY_USERINFO)

and it displays this messages on the Screen, in the way or whereever I want it to...

The reason why I want to know the passed pointer type is simple, that when I init a Message like

Message(DISPLAY_MOUSE_COORD, "Those are my coordinates: X %f and Y %f", gMouse->GetX(), gMouse->GetY);

I do not want to look up if GetX() was a double or an int or whatever. I wanted it to be figured out by itself. Something like that

Message(DISPLAY_WHATEVER, "Those are my coordinates: X %w and Y %w and you are %w years old", gMouse->GetX(), gMouse->GetY, User->GetAge());

while %w is being replaced with the right type of pointer value. Why? I want to have sometimes 4 different variables passed, for instance:

Message(int TYPE, string, double, double, int, double" and without the need to overload Message a hundred of times when considering all the different combinations of doubles, ints and strings...


Ive also tried Templates which do the very same job, however, a flexible void pointer is more satisfying, since I want to pass as many arguments as needed. I tried a template at first but it did not work out that good:

template <class T>
void gFont::AddTest (int passedPosition, std::string passedString, T &passedVar, T &passedVar2)

as this only passed two ints at the same time. I would need two different templates within one function, but I haven't figured out a way to do this and it seems pretty strange. Thus a void pointer seemed to be the most powerful way.

Regards

Thus a void pointer seemed to be the most powerful way.

Void pointers are powerful, but you lose any kind of type checking when you use them. That is the trade off. This message system has the same problem that printf() does, and which the iostream library overcomes. There is no way to check that the argument types match the format string.

The only thing I can think of without overhauling the entire system to be type safe is a master template:

template <class T1, class T2, class T3, 
          class T4, class T5, class T6>
void gFont::AddTest (int passedPosition, 
                     std::string passedString, 
                     T1 &var1=T1(), T2 &var2=T2(), T3 &var3=T3(),
                     T4 &var4=T4(), T5 &var5=T5(), T6 &var6=T6())

With the default values you can pass fewer than the maximum and just ignore the ones that are not in the format string. As long as the master template supports as many parameters as you pass, it will work.

Mastertemplates... now that is something I can work on! Many thanks to you!

The only thing I can think of without overhauling the entire system

What do you have in mind? My programm is still, I believe, flexbible enough to handle an overhaul. However, the system now is with my limited C++ knowlege the best I could come up so far. If you hint me in the right direction I can look into it.. I am always glad to learn something new..

I mentioned printf() and how the iostream library fixes the type safety problem. That is a good place to start, but it means that you will not be able to use format strings in the same way, and there will be lots of overloading for different types.

To be honest, I am not sure how I would solve this problem. Maybe after a day or two letting it simmer, I can give you a better answer. :)

I'd say, you did already give a great answer.. I implemented the master Templates now you given me and it works just fine, however, I do not understand the bit of additional of code you provided, as you write

void AddTest3 (int passedPosition,
                     std::string passedString,
                     T1 &var1=T1(), T2 &var2=T2())

Why ... T1 &var=T1(), T2 &var=T2()?

and not simply

.. T1 &var, T2 &var

does the appendix =T1() has an additional meaning?

And... about simmering

iostream library fixes the type safety problem

I guess so.. I wish I had a better understanding of stdio than just std::string.. I'd love to do something beautiful like...

gFont->Message ("This is this" << varDouble << "and dats dat" << varInt);

but since the message system is just a smaller sub system in my application, its queentask is to perform its job safely and quietly and do nice graphics! Also the fontload underlying the messagesystem works with a printf similar system and I do not want to mengle with it.

I am really really happy with the template example you provided me. I was exactly looking for that, but was not aware how to do multiple templates b4.

Why ... T1 &var=T1(), T2 &var=T2()?

and not simply

.. T1 &var, T2 &var

does the appendix =T1() has an additional meaning?

If you have a function that takes 4 parameters, you have to provide all parameters when calling it:

#include <iostream>

void function(int a, int b, int c, int d)
{
    std::cout << a << '\t'
              << b << '\t'
              << c << '\t'
              << d << '\n';
}

int main()
{
    function();           // error
    function(1);          // error
    function(1, 2);       // error
    function(1, 2, 3);    // error
    function(1, 2, 3, 4); // ok
}

The additional code I added was default values for the parameters. With default values, if you do not provide enough arguments, the default values are used and the function looks like it is overloaded:

#include <iostream>

void function(int a=0, int b=0, int c=0, int d=0)
{
    std::cout << a << '\t'
              << b << '\t'
              << c << '\t'
              << d << '\n';
}

int main()
{
    function();           // ok
    function(1);          // ok
    function(1, 2);       // ok
    function(1, 2, 3);    // ok
    function(1, 2, 3, 4); // ok
}

For a template argument called T, T() is the default value for that type. So for T==int, T() is 0. For T==string, T() is "". The template I wrote says that all of the parameters with a template argument type have a default value of the template argument type. :)

Again a genious strike of yours! I am shattered. Not bad.. I need too much to learn.. *humble*

I'd say thats done now and lets move on with our lives... Topic closed

Additional note for people checking up on this topic...

Using the neat code Tom Gunn provided about multiple templates, I figured I still need to make a reinterpret_cast call despite of using

if (typeid(T1) ==typeid(int))

If I do not use reinterpret_cast I get an error message:

D:\C++ Projects\Project1\project.cpp|1950|error: cannot convert `double*' to `int*' in assignment|

The reason for that is probably that the compiler ignores the typecheck if statement as it does not really know what will be passed after all, however on runtime everything works as it should. Thus forcing the compiler with reinterpret_cast to take an int really for an int and take a double for an double works best...

template <class T1, class T2>
void gFont::AddTest3 (int passedPosition,
                     std::string passedString,
                     T1 *var1=T1(), T2 *var2=T2())
    {
        gMessage* aMessage =  new gMessage(1, passedString);

        if (typeid(T1) == typeid(int))
            {
            aMessage->nItsVars=0;


        //reinterpret_cast<int*> is needed, otherwise I get 
       the described compiler error
  
        aMessage->pInt=reinterpret_cast<int*>(var1); 


            vMessages[passedPosition]=aMessage;
            nMessages++;

            std::cout << "that was an int";
            std::cout << *aMessage->pInt;
            }

        if (typeid(T1) == typeid(double))
            {
            aMessage->nItsVars=0;
            //reinterpret_cast<double> for this if statement is needed
            aMessage->pDouble=reinterpret_cast<double*>(var1); 
            vMessages[passedPosition]=aMessage;
            nMessages++;

            std::cout << "that was an double";
            std::cout << *aMessage->pDouble;
            }

    }

It should be hopefully safe.. ;)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.