No, of course not.
Should probably get rid of the vector in the struct, too.Code:struct IntStr { IntStr(int x): i(x) {} IntStr(const char* str): s(str) {} int i; string s; };
I went ahead and added the constructors:
Now, if I don't haveCode:struct IntStr { int i; IntStr(int x): i(x) {} string s; IntStr(const char* y): s(y) {} vector<IntStr> v; }; int main() { IntStr temp; temp.i = 123; temp.s = "abc"; temp.v.push_back(789); temp.v.push_back("xyz"); }
andCode:IntStr(int x): i(x) {}
then the compiler complains at temp.v.Code:IntStr(const char* y): s(y) {}
If I do have them, then
the compiler says
no matching function for call to `IntStr::IntStr()'
candidates are: IntStr::IntStr(const IntStr&)
IntStr::IntStr(const char*)
IntStr::IntStr(int)
at
Code:IntStr temp;
This is confusing
Confusing? Nothing of the sort! You lack understanding of the basic rules! And you call yourself a C++ programmer!?! Just kidding
When you add specialized constructors, the compiler doesn't substitute a default constructor for you, so you'll have to add it manually:
Code:struct IntStr { IntStr() {} IntStr(int x): i(x) {} IntStr(const char* y): s(y) {} int i; string s; };
Yeah but I'm still learning things though. I'm a C++ programmer since I use C++, but I never said I was good at it.
I just take notes as I go along
Is there a way to do this:
ThanksCode:#include <iostream> #include <string> #include <vector> using namespace std; struct IntStr { IntStr() {} int i; IntStr(int ii): i(ii) {} string s; IntStr(const char* ss): s(ss) {} vector<IntStr> v; IntStr(vector<IntStr> vv): v(vv) {} }; int main() { IntStr temp; //works temp.i = 123; //works cout << temp.i << endl; //works temp.s = "abc"; //works cout << temp.s << endl; //works temp.v.push_back(123789); //works temp.v.push_back("abcxyz"); //works cout << temp.v.size() << endl; //outputs 2 (proof that v is holding the two elements) //cout << temp.v.at(0) << endl; //Compiler complains here //cout << temp.v.at(1) << endl; //Compiler complains here }
I wonder if what you really want is a structure that involves a union. Because it seems like sometimes you want a specific item in the vector to be a string, and at other times an int.
Can it be done with a union?
I was using struct because I noticed the compiler did not complain by doing
before the struct IntStr was completed.Code:vector<IntStr>
I thought this self-reference would allow me to use vectors of both int and string by defining the int and string inside of the struct.
In order to overload <<
would I do something like this:
Code:IntStr operator<<(const int index) //index number with associated element { return v.at(index); }
When you chose to use a structure, you're saying you needed both the int and the string version. Hence when you push back something to the vector, it should be the whole structure, not just an integer or just a string.
I'm saying you could do something like:
The union comment was more of a source of inspiration, considering the way you want your object to behave. Actually using a union here would be bothersome, as unions cannot contain objects, so you would have to manage a char* string.Code:class IntStr { public: IntStr (const char* init) { SetString (init); } IntStr (int init) { SetInt (init); } IntStr () { mTypeInfo = UNION; } bool GetString (const char *&retval) { if (mTypeInfo == STRING) { retval = mIntStr.mStr; return false; } else if (mTypeInfo == INTEGER) { std::ostringstream conv; conv << mIntStr.mInt; if (conv) { SetString (conv.str().c_str()); retval = mIntStr.mStr; return false; } else { return true; } } else { return true; } } bool GetInt (int &retval) { if (mTypeInfo == INTEGER) { retval = mIntStr.mInt; return false; } else if (mTypeInfo == STRING) { std::istringstream conv; conv.str(mIntStr.mStr); int temp; conv >> temp; if (conv) { SetInt (temp); retval = mIntStr.mInt; return false; } else { return true; } } else { return true; } } void SetString (const char *init) { mTypeInfo = STRING; mIntStr.mStr = init; return ; } void SetInt (int init) { mTypeInfo = INTEGER; mIntStr.mInt = init; return ; } private: typedef enum { INTEGER, STRING, UNION } MyType; MyType mTypeInfo; union IntStrTag { const char *mStr; int mInt; } mIntStr; };
Rather, have your object contain both a string and an int, and have an interface like this one, Let the object treat its value like an int or a string at any given time, just like a union.
Honestly, I have no idea where you are trying to get with this idea, or even why you would do such a thing. But you were already pointed out, by laserlight, I believe, of a boost class, Boost.Variant, I believe, that would do this for you. Essentially a C++ union.
Before we do anything else, I think it's better if we ask you what exactly you want to do and why.
Thanks, it works WhiteFlags.
How do I use the << operater on the IntStr type?
I tried this:
It fails, but aside from that, the compiler did not complain at the following declarationsCode:IntStr IntStr::operator<< (IntStr argument) { return argument; }
Oh and I'm just testing different ways of doing things.Code:IntStr number; number = 123; IntStr letter; letter = "abc";
I do remember about LaserLight's suggestion of Boost::Variant.
Such as?
Of course your assignments would work as your constructors take care of that implicit conversion.
To overloaded <<, remember what it must take. You are placing cout on the left side, which is an ostream and the right is an IntStr, so construct your operator from that.
Thanks.
Would it look something like this?
Code:ostream &operator<<(ostream &output, IntStr intstr) { if (mTypeInfo == INTEGER) output << intstr.mInt; elif (mTypeInfo == STRING) output << intstr.mStr; return output; } istream &operator>>(istream &input, IntStr intstr) { if (mTypeInfo == INTEGER) input >> intstr.mInt; elif (mTypeInfo == STRING) input >> intstr.mStr; return input; }
Oh I was hoping to relate to the mTypeInfo within the class. Overloading operators must be done outside of the class and referred to with friend, right?
Is the operator>> incorrect because of the reference (&) before it?
istream input instead of istream &input ?
If I ignored inputs for now, how could I make it so that it outputs a string or int within the union depending on the type?
Would I use
typeid().name()
or would that simply return a union type?
Thanks.