i'm updating my variant type
(please forget the boost::variant.. i have test it and i give up on it)
i'm update my class for accept the class's\structs and more.
see the entire class:
Code:
#ifndef VARIANT_H_INCLUDED
#define VARIANT_H_INCLUDED
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class variant
{
private:
bool blnvoid;
string a;
void *b;
public:
variant()
{
blnvoid=false;
a="";
b=NULL;
}
variant (string value)
{
a=value;
}
variant (double value)
{
a=to_string(value);
}
variant (int value)
{
a=to_string(value);
}
variant (long value)
{
a=to_string(value);
}
variant (void *value)
{
blnvoid=true;
b=value;
}
friend istream& operator >>(istream &is,variant &obj)
{
is>>obj.a;
return is;
}
friend ostream& operator <<(ostream &os,const variant &obj)
{
if (blnvoid==true) //here cames the error and i don't know why :(
{
os << obj.b;
}
else
{
os << obj.a;
}
return os;
}
friend istream &getline(istream &in, variant &s1)
{
getline(in, s1.a);
return in;
}
variant & operator = (int const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (long const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (string const &b)
{
a=b;
return *this;
}
variant & operator = (double const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (float const & b)
{
a=to_string(b);
return *this;
}
bool operator == (string const & b)
{
return (a==b);
}
operator string() const
{
return a; // return string member
}
operator double() const
{
return atof(a.c_str()) ;
}
};
#endif // VARIANT_H_INCLUDED
error messages:
- "In function 'std::ostream& operator<<(std::ostream&, const variant&)':";
- "error: invalid use of non-static data member 'variant::blnvoid'";
- "error: from this location".
i don't understand these errors :(
can anyone explain to me?
Re: i'm updating my variant type
Quote:
if (blnvoid==true) //here cames the error and i don't know why :(
blnvoid is a member of the class variant. The function operator<< is not a member of this class and so can't directly access this variable. You are passing obj as a reference to a variant class so use
Code:
if (obj.blnvoid == true)
Re: i'm updating my variant type
Quote:
Originally Posted by
2kaud
blnvoid is a member of the class variant. The function operator<< is not a member of this class and so can't directly access this variable. You are passing obj as a reference to a variant class so use
Code:
if (obj.blnvoid == true)
thanks for correct me... thanks
Re: i'm updating my variant type
see these test:
variant d=100;
why i get a hexadecimal result with cout?
Re: i'm updating my variant type
because i didn't change the blnvoid value ;)
Code:
#ifndef VARIANT_H_INCLUDED
#define VARIANT_H_INCLUDED
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class variant
{
private:
bool blnvoid;
string a;
void *b;
public:
variant()
{
blnvoid=false;
a="";
b=NULL;
}
variant (string value)
{
blnvoid=false;
a=value;
}
variant (double value)
{
blnvoid=false;
a=to_string(value);
}
variant (int value)
{
blnvoid=false;
a=to_string(value);
}
variant (long value)
{
blnvoid=false;
a=to_string(value);
}
variant (void *value)
{
blnvoid=true;
b=value;
}
friend istream& operator >>(istream &is,variant &obj)
{
is>>obj.a;
return is;
}
friend ostream& operator <<(ostream &os,const variant &obj)
{
if (obj.blnvoid==true)
{
os << obj.b;
}
else
{
os << obj.a;
}
return os;
}
friend istream &getline(istream &in, variant &s1)
{
getline(in, s1.a);
return in;
}
variant & operator = (int const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (long const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (string const &b)
{
a=b;
return *this;
}
variant & operator = (double const & b)
{
a=to_string(b);
return *this;
}
variant & operator = (float const & b)
{
a=to_string(b);
return *this;
}
bool operator == (string const & b)
{
return (a==b);
}
operator string() const
{
return a; // return string member
}
operator double() const
{
return atof(a.c_str()) ;
}
};
#endif // VARIANT_H_INCLUDED
now i can test the the void pointer;)
Re: i'm updating my variant type
is there anyway for test if void pointer type is int\long\double\string?
Re: i'm updating my variant type
A void pointer is a void pointer is a void pointer! Its up to the user of a void pointer to cast it to whatever type they want. If you mean can you test for the type that was originally cast to a void pointer - then no.
You can, however, do something this like this
Code:
#include <iostream>
using namespace std;
enum vtype {vint, vlong, vdouble};
struct typei {
vtype vt;
int myint;
};
struct typed {
vtype vt;
double mydouble;
};
void processvoid(void *v)
{
typei *vp = (typei *)v;
switch (vp->vt) {
case vint:
{
typei *vi = (typei*) vp;
cout << "Got an integer " << vi->myint << endl;
}
break;
case vdouble:
{
typed *vd = (typed*) vp;
cout << "Got a double " << vd->mydouble << endl;
}
break;
}
}
int main()
{
typed dou;
typei ingr;
dou.vt = vdouble;
dou.mydouble = 23.45;
ingr.vt = vint;
ingr.myint = 7;
void * v1 = (void*)&dou;
void * v2 = (void*)&ingr;
processvoid(v1);
processvoid(v2);
return 0;
}
This 'works' because the variable vt is the same in each struct and is always the first element of the struct - so casting the void pointer to any valid type will then allow the value of vt to be determined so that it can then be cast to the correct type based upon the value of vt.
This method is commonly used with WM_NOTIFY windows message so that different structs can be passed using the same parameter.
Re: i'm updating my variant type
Quote:
Originally Posted by
2kaud
A void pointer is a void pointer is a void pointer! Its up to the user of a void pointer to cast it to whatever type they want. If you mean can you test for the type that was originally cast to a void pointer - then no.
You can, however, do something this like this
Code:
#include <iostream>
using namespace std;
enum vtype {vint, vlong, vdouble};
struct typei {
vtype vt;
int myint;
};
struct typed {
vtype vt;
double mydouble;
};
void processvoid(void *v)
{
typei *vp = (typei *)v;
switch (vp->vt) {
case vint:
{
typei *vi = (typei*) vp;
cout << "Got an integer " << vi->myint << endl;
}
break;
case vdouble:
{
typed *vd = (typed*) vp;
cout << "Got a double " << vd->mydouble << endl;
}
break;
}
}
int main()
{
typed dou;
typei ingr;
dou.vt = vdouble;
dou.mydouble = 23.45;
ingr.vt = vint;
ingr.myint = 7;
void * v1 = (void*)&dou;
void * v2 = (void*)&ingr;
processvoid(v1);
processvoid(v2);
return 0;
}
THis 'works' because the variable vt is the same in each strut and is always the first element of the struct - so casting the void pointer to any valid type will then allow the value of vt to be determined so that it can then be cast to the correct type based upon the value of vt.
This method is commonly used with WM_NOTIFY windows message so that different structs can be passed using the same parameter.
thanks for that.
i need change anotherthing:
Quote:
variant (void *value)
the void pointer accept any type, but with variable adress. can i change it for accept the variable name?
Re: i'm updating my variant type
Quote:
the void pointer accept any type, but with variable adress. can i change it for accept the variable name?
I'm not sure I understand the question?:confused:
Re: i'm updating my variant type
Quote:
Originally Posted by
2kaud
I'm not sure I understand the question?:confused:
sorry.. i did a mistake... maybe i can see better.. sorry
see these exemple:
Code:
std::vector<int> b;
b.resize(3);
b[0]=100;
b[1]=200;
b[2]=300;
variant d=&b;
cout << d;
(instead a vector i can use a structure or other)
please explain better to me the vector and a class for i use with my variant class.. please
Re: i'm updating my variant type
b is a vector of int. So &b is the address of a vector of int. So d is an address of a vector of int. You are trying to assign type of address of a vector of int to a type of class variant. This doesn't work. For it to work, you would need a constructor for class variant that accepted a vector of int. Then you could do variant d = b;
You could do variant d = (void*)&b; if your variant class had a constructor for a type void *.
As I said in a previous post, I would avoid using type of void *.
Re: i'm updating my variant type
Quote:
Originally Posted by
2kaud
b is a vector of int. So &b is the address of a vector of int. So d is an address of a vector of int. You are trying to assign type of address of a vector of int to a type of class variant. This doesn't work. For it to work, you would need a constructor for class variant that accepted a vector of int. Then you could do variant d = b;
You could do variant d = (void*)&b; if your variant class had a constructor for a type void *.
As I said in a previous post, I would avoid using type of void *.
sorry i want avoid the boost::any i have tested.
Code:
variant (void *value)
{
blnvoid=true;
b=(void*) &value;
}
(i think isn't correct :()
but for use in cout, i must use like another pointer?
Re: i'm updating my variant type
Quote:
but for use in cout, i must use like another pointer?
cout must know the type of the argument the value of which it is to display. You can overload the operator << to enable cout to display a type of which it doesn't know already - but in the code for the operator<< function, you will need to know the type of what you are trying to display.
My previous example in post #7 could be extended for vectors by something like this
Code:
#include <iostream>
#include <vector>
using namespace std;
enum vtype {vint, vlong, vdouble, vvecint};
struct typei {
vtype vt;
int myint;
};
struct typed {
vtype vt;
double mydouble;
};
struct vecint {
vtype vt;
vector<int> *pvcti;
};
void processvoid(void *v)
{
typei *vp = (typei *)v;
switch (vp->vt) {
case vvecint:
{
vecint *vint = (vecint*) vp;
cout << "Got a vector of int " << endl;
for (vector<int>::const_iterator ci = vint->pvcti->begin(); ci != vint->pvcti->end(); ++ci)
cout << *ci << endl;
}
break;
case vint:
{
typei *vi = (typei*) vp;
cout << "Got an integer " << vi->myint << endl;
}
break;
case vdouble:
{
typed *vd = (typed*) vp;
cout << "Got a double " << vd->mydouble << endl;
}
break;
}
}
int main()
{
typed dou;
typei ingr;
vecint tvint;
vector<int> vcint;
vcint.resize(3);
vcint[0] = 100;
vcint[1] = 200;
vcint[2] = 300;
tvint.vt = vvecint;
tvint.pvcti = &vcint;
dou.vt = vdouble;
dou.mydouble = 23.45;
ingr.vt = vint;
ingr.myint = 7;
void * v1 = (void*)&dou;
void * v2 = (void*)&ingr;
void * v3 = (void*)&tvint;
processvoid(v1);
processvoid(v2);
processvoid(v3);
return 0;
}
Your variant class will probably have to do something similar in order to be able to do what you are trying.
Re: i'm updating my variant type
Quote:
Originally Posted by
Cambalinho
sorry i want avoid the boost::any i have tested.
Why are you playing all of these games with the void pointer?
All a void pointer knows is that it's a void pointer. There is no "secret way" of detecting what a void pointer is pointing to. That is the bottom line. All you're doing now is coming up with hacks that won't work if someone were to use a type you aren't thinking of. How are you going to handle a vector<double>? A vector<float>? A std::set<int>? A std::map<int, int>? A std::map<double, double>? A Widget? A tuple<int, double, char>? etc. etc. etc. How is your void pointer going to know how to adjust to any type the user comes up with?
It's pointless for the called function to try and figure out what the variant is pointing to, unless there is an agreement between the caller and called function as to how to specify the type that really is being pointed to. And even then, the use of void pointer isn't needed, as both the called function and the caller knows the available types (You then have the Java-like "god Object" class. If you don't know what I mean, look up the "Object" class in Java, and why most C++ programmers avoid this paradigm).
Regards,
Paul McKenzie
Re: i'm updating my variant type
But why are you doing all this 'messing about' with void pointers? If you just pass void pointers, then somewhere you are still going to have to decide what type they should be before you do anything useful with them. You can't determine the type that was cast to a void pointer just from having a pointer to void!
This is where templates come into play. You code one template function or class which can then be used for different types. The template doesn't need to know about the type of which it was called. IMO I would forget about void pointers.