Thread: istream overload

  1. #1
    Registered User
    Join Date
    Sep 2002
    Posts
    417

    istream overload

    Here I am doing more stuff with my "any" type.

    I'm overloading the istream operator right now... I can't figure out why it isn't working right.

    As far as the function itself, that works. Locally, the commented out any_cast line returns the correct value.

    But it isn't acting like it actually changed the passed "operand"... because it doesn't do a thing if you try to use any_cast outside of the overload.

    Any ideas as to what is wrong? Thanks!

    Code:
    	istream& operator >>(istream & is, any & operand)
    	//precondition:  input stream is open for reading
    	//postcondition: the next string from input stream is has been read
    	//               and stored in str
    	{
    		char temp[81] = "";	// not longer than screen length
    		char ch = 0;
    		int i = 0;
        
    		while (i <= 80 && is.get(ch) && ch != '\n')
    		{
    			temp[i++] = ch;
    		}
    		temp[i] = '\0';
    
    		operand = temp;
    
    		//cout << any_cast<char*>(operand) << endl;
        
    		return is;
    	}
    And if it does work, I get giberish characters.
    Last edited by Trauts; 05-06-2003 at 07:16 PM.

  2. #2
    Registered User
    Join Date
    Sep 2002
    Posts
    417
    if I add a line like this:

    operand = 'a';

    then it works fine... it gives me an a later. But if I give it the value of temp... it doesn't

    Its also useless to always assign it a value.
    Last edited by Trauts; 05-06-2003 at 07:26 PM.

  3. #3
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    pointers to local variables are always invalid after leaving scope, even if you wrap them in a fancy union. Use std::string. I also see no point to having an any that takes on only one value. I think you want something like.

    Code:
    boost::any gettok(std::istream &is) {
        std::string str;
        is >> str;
        if(is) {
            try {
                int i = boost::lexical_cast<int>(str);
                return boost::any(i);
            }  catch(bad_cast &e) {
                return boost::any(str);
            }
        } else {
             return boost::any((void *)0);
        }
    }

  4. #4
    Registered User
    Join Date
    Sep 2002
    Posts
    417
    I was specifically trying not to use a string.

    I understand what you're saying (I've had that problem before)... but where was I using pointers?

    and btw, I'm not actually using boost, its just something from boost... so I don't have lexical cast.

    Originally posted by grib
    I also see no point to having an any that takes on only one value.
    It won't always take a string, trust me... I just want to get it working with strings first.
    Last edited by Trauts; 05-06-2003 at 07:29 PM.

  5. #5
    Registered User
    Join Date
    Sep 2002
    Posts
    417
    eh you're right about the pointers (it works with an int)... but I want to use a character array.

    How might I do this?

    right now, my newest code is this:

    Code:
    	istream& operator >>(istream & is, any & operand)
    	//precondition:  input stream is open for reading
    	//postcondition: the next string from input stream is has been read
    	//               and stored in operand
    	{
    		char temp[81];	// not longer than screen length
    		char ch;
    		int i = 0;
        
    		while (i <= 80 && is.get(ch) && ch != '\n')
    			temp[i++] = ch;
    
    		temp[i] = '\0';
    
    		//cout << any_cast<char*>(operand) << endl;
    
    		if (strcmp(operand.type().name(),"int")==0)
    			operand = atoi(temp);
    		else if (strcmp(operand.type().name(),"float")==0 || strcmp(operand.type().name(),"double")==0)
    			operand = atof(temp);
    		else
    			operand = temp;
       
    		return is;
    	}

  6. #6
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    If you must use a char*, and I don't see why, and you must also use a >> overload, and it must be an overload of any, wrather than a wrapper class then you have very few choices.

    1. only allow reading a cstring into an any that already is a cstring. That is set any to point to a char array in the calling function before doing cin >> myany. Then use
    char *temp = any_cast<char *> operand

    2. use strdup() and remember to call free() on any's that happen to hold char*, being careful to never call an any that holds a char* that points to memory not allocated with strdup()

    3. Use a static in operator >> and work with only one any at a time.

    I strongly suggest that you create your own class, perhaps using any in it's implementation, It looks like what you want is closer to a variant type, rather than a discriminated union.

    A further point, typeid.name() makes for a nice debug message, but it's not something that you want to rely on.
    if(operand.type() == typeid(int))
    is the normal way you want to do this.

  7. #7
    Registered User
    Join Date
    Sep 2002
    Posts
    417
    that was actually a temporary solution. I know what you mean though.

    any isn't a union... it is a variant.

    It works exactly like I want it to... except it goes out of scope.

    static would work, only the variable is always the same, so if you call it again, the other value changes.

    Here's my latest code:

    Code:
    	istream& operator >>(istream & is, any & operand)
    	//precondition:  input stream is open for reading
    	//postcondition: the next string from input stream is has been read
    	//               and stored in operand
    	{
    		static char temp[81];	// not longer than screen length
    		char ch;
    		int i = 0;
        
    		while (i <= 80 && is.get(ch) && ch != '\n')
    			temp[i++] = ch;
    
    		temp[i] = '\0';
    
    		//cout << any_cast<char*>(operand) << endl;
    
    		if (isint(temp))			// if it is an integer, convert it to one
    			operand = atoi(temp);
    		else if (isfloat(temp))		// if it is a float or double, convert it to one
    			operand = atof(temp);
    		else						// otherwise, just store a string
    			operand = temp;
       
    		return is;
    	}
    Last edited by Trauts; 05-06-2003 at 08:56 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stupid compiler errors
    By ChrisEacrett in forum C++ Programming
    Replies: 9
    Last Post: 11-30-2003, 05:44 PM
  2. Having trouble with operator*=()
    By Lurker in forum C++ Programming
    Replies: 10
    Last Post: 10-26-2003, 03:03 PM
  3. Replies: 3
    Last Post: 09-27-2003, 06:57 PM
  4. Replies: 5
    Last Post: 11-24-2002, 11:05 PM
  5. <list>
    By Unregistered in forum C++ Programming
    Replies: 9
    Last Post: 02-24-2002, 04:07 PM