Thread: operator '>>' reuse

  1. #46
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Maybe we go about this discussion the wrong way:
    The operator>> is an operator. Just like operator + in a + b, you expect it to behave in a certain way - namely in the latter case add the two values together, and in the former, to serialize (output to a stream) the data.

    We do not want our long integer class operator+ to contain code to input two variable and then add their values. You could possibly have a class that has a function to do that, but it's not the operator +.

    A "InputContractFromUser" is different from a operator>>.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #47
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by matsp View Post
    Maybe we go about this discussion the wrong way:
    The operator>> is an operator. Just like operator + in a + b, you expect it to behave in a certain way - namely in the latter case add the two values together, and in the former, to serialize (output to a stream) the data.

    We do not want our long integer class operator+ to contain code to input two variable and then add their values. You could possibly have a class that has a function to do that, but it's not the operator +.

    A "InputContractFromUser" is different from a operator>>.

    --
    Mats
    In essence you guys are saying to me, i should keep ONLY the following function as a valid operator overloading... Is this basically what i should be doing in all other classes?

    Code:
    std::ifstream& operator >> (std::ifstream& in, Contract& contract)
    {
    	std::string contractID;
    	std::string rentalType;
    	std::string carReg;
    	char carGrp;
    
    	in >> contractID;
    	in >> carReg;
    	in >> carGrp;
    	in >> rentalType;
    
    	contract.SetContractDetails(carReg, rentalType, carGrp);
    
    	return in;
    }
    Which suggests to me that it will only work when reading from a file stream, since the command prompt will ALWAYS require prompts & input validations ...

    So, the following will then make sense

    Code:
    void Rental::readContractDetails ()
    {
    	std::string rentalType;
    	std::string carReg;
    	char carGrp;
    
    	system("cls");
    
    	std::cout << "\n     \t\t\tÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n";
    	std::cout << "     \t\t\tº         CONTRACT DETAILS      º\n";
    	std::cout << "     \t\t\t\314ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\271\n";
    
    	std::cout << "\n\n\nEnter new contract data below..." << std::endl;
    	
    	std::cout << "\n1. Car registration number : ";
    	std::cin >> carReg;
    
    	std::cout << "\n2. Rental group [A/B/C/D/F/O/Z] : ";
    	std::cin >> carGrp;
    
    	std::cout << "\n3. Rental Type [\"Unlimited\" OR \"200km\"]" ;
    	std::cin >> rentalType;
    
    	contract.SetContractDetails(carReg, rentalType, carGrp);
    }
    Above, i have two functions, one is a friend to class Contract (the '>>') and reads data from file, the other also reads Contract details but from the user and but is free from Contract class ...

  3. #48
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    In essence you guys are saying to me, i should keep ONLY the following function as a valid operator overloading... Is this basically what i should be doing in all other classes?
    Continue to overload with respect to std::istream, not std::ifstream. Although its intended use is to read from a file, this leaves the option of using it to read from say, piped standard input.

    Above, i have two functions, one is a friend to class Contract (the '>>') and reads data from file, the other also reads Contract details but from the user and but is free from Contract class ...
    That sounds good.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #49
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by laserlight View Post
    Continue to overload with respect to std::istream, not std::ifstream. Although its intended use is to read from a file, this leaves the option of using it to read from say, piped standard input.


    That sounds good.
    Cool, we getting somewhere... Now! the following ...

    Code:
    // Read driver's address from input stream
    bool Address::ReadFromFile(std::istream& indata)
    {
    	indata >> *this;	
    	return indata.fail();
    }
    This is the function which calls the overloaded operator .. My thoughts are it shouldn't be tied to any of the objects/classes ... My thoughts are to make its second argument a Template that it may accept any object, and begin to call the appropriate overloaded '>>'. I haven't worked with templates a t all, this is my attempt though..

    Code:
    template <class T>
    bool Rental::ReadFromFile <T>(std::istream& indata, T object)
    {
    	indata >> object;	
    	return indata.fail();
    }
    
    // Calling it toread Driver details from file
    
    ReadFromFile<Driver>(fin, driver);
    If this is correct, where exactly do i place this line 'template <class T>'... above class Rental declaration maybe?
    Last edited by csonx_p; 08-29-2008 at 10:57 AM.

  5. #50
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by csonx_p View Post
    Cool, we getting somewhere... Now! the following ...

    Code:
    // Read driver's address from input stream
    bool Address::ReadFromFile(std::istream& indata)
    {
    	indata >> *this;	
    	return indata.fail();
    }
    This is the function which calls the overloaded operator .. My thoughts are it shouldn't be tied to any of the objects/classes ... My thoughts are to make its second argument a Template that it may accept any object, and begin to call the appropriate overloaded '>>'. I haven't worked with templates a t all, this is my attempt though..

    Code:
    template <class T>
    bool Rental::ReadFromFile <T>(std::istream& indata, T object)
    {
    	indata >> object;	
    	return indata.fail();
    }
    
    // Calling it toread Driver details from file
    
    ReadFromFile<Driver>(fin, driver);
    If this is correct, where exactly do i place this line 'template <class T>'... above class Rental declaration maybe?
    It goes where you put it. The <T> doesn't belong though.

  6. #51
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by tabstop View Post
    It goes where you put it.
    What i have above is the definition of ReadFromFile (inside rental.cpp). If i leave it where i have it, how would the 'prototype' be happy with T, since is located on a different file (Rental.h)

    The <T> doesn't belong though.
    Not understanding ????

  7. #52
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Your .h file should have:
    Code:
    template <class T>
    bool Rental::ReadFromFile(std::istream& indata, T object)
    {
    	indata >> object;	
    	return indata.fail();
    }
    In other words, the template attaches to the actual function itself, not where it's called. Notice also the complete lack of <T> in the definition. (You use angle brackets when you call it, not when you define it.)

    (Edit: Note that when using templates, you put the whole thing in the header file, since the template body must be visible from where it is called, and header files are the easiest way to make that happen.)

    Edit edit: Or, if you are feeling a little rebellious, AND the only place this function is called is from the .cpp file, you can put the whole template in the .cpp file instead. But if any other file needs one of those functions, it has to be in the header.
    Last edited by tabstop; 08-29-2008 at 11:39 AM.

  8. #53
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Incidentally, it should probably be:
    Code:
    template <class T>
    bool Rental::ReadFromFile(std::istream& indata, T& object)
    {
    	indata >> object;
    	return indata.fail();
    }
    Some people use typename instead of class when the template argument is not necessarily a class type, but otherwise the two keywords are equivalent in this context.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #54
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by laserlight View Post
    Incidentally, it should probably be:
    Code:
    template <class T>
    bool Rental::ReadFromFile(std::istream& indata, T& object)
    {
    	indata >> object;
    	return indata.fail();
    }
    Some people use typename instead of class when the template argument is not necessarily a class type, but otherwise the two keywords are equivalent in this context.
    does this look ok ..

    Code:
    #ifndef RENTAL_H
    #define RENTAL_H
    
    #include "Contract.h"
    #include "Driver.h"
    #include <vector>
    
    class Rental
    {
    private:
    	typedef std::vector<Contract> RentalContract;
    	typedef RentalContract::iterator ContractsIterator;
    
    public:
    
    	Rental();
    	~Rental();
    
    	void CreateNewContract();
    	void DeleteContract();
    	void ViewContract();
    	void ReadNewAddress();
    	void ReadNewContract(const std::string& id);
    	void ReadNewDriverDetails(std::string* refNo);
    	
    		
    	template <class T>
    	bool ReadFromFile (std::istream& indata, T& data)
    	{
    		indata >> data;	
    		return indata.fail();
    	}
    
    	ContractsIterator find(); 
    	
    private:
    	RentalContract contractList;
    	Contract contract;
    	Driver driver;
    };
    
    #endif

  10. #55
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I suppose so, but in retrospect, the function template looks out of place. It does a very generic job: call the overloaded operator>> for T. In fact, it is so generic that it does not belong in your class, and perhaps is not needed at all. The very reason for a ReadFromFile() member function in the first place was to have interactive input from the user into the object, but this is no longer the case in your ReadFromFile function template.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #56
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by laserlight View Post
    I suppose so, but in retrospect, the function template looks out of place. It does a very generic job: call the overloaded operator>> for T. In fact, it is so generic that it does not belong in your class, and perhaps is not needed at all. The very reason for a ReadFromFile() member function in the first place was to have interactive input from the user into the object, but this is no longer the case in your ReadFromFile function template.
    Wait. I thought we were going to have a ReadFromFile, which did a lot of >> type things, and a ReadFromUser, which was going to be the interactive input.

  12. #57
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by laserlight View Post
    I suppose so, but in retrospect, the function template looks out of place. It does a very generic job: call the overloaded operator>> for T. In fact, it is so generic that it does not belong in your class, and perhaps is not needed at all. The very reason for a ReadFromFile() member function in the first place was to have interactive input from the user into the object, but this is no longer the case in your ReadFromFile function template.
    Eish, now there am getting confused again or should i just make it a free function, then everything will be fine... Anyway, i have a quick question ..

    Code:
    void Rental::ReadNewDriverDetails(std::string* refNo)
    {
    	std::string fname, sname, contact;
    	std::string IDNo;
    
    	system("cls");
    	
    	std::cout << "\n     \t\t\t&#201;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#187;\n";
    	std::cout << "     \t\t\t&#186;         DRIVER DETAILS        &#186;\n";
    	std::cout << "     \t\t\t\314&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;\271";
    
    	std::cout << "\n\n\nEnter the following Driver's details\n\n";
    	
    	std::cout << "\nFull Name : "; 
    	std::in >> fname >> sname;
    
    	std::cout << "\nDriver's ID Number : ";
    	std::in >> IDNo;
    	*refNo  = IDNo;
    	
    	std::cout << "\nContact Number [ccc-ddd-dddd] : ";
    	std::in >> contact;
    
            // Here's my question
    	driver.SetAddress( ReadNewAddress(driver.getAddress()) );
    	
    	driver.SetDriverDetails(fname, sname, IDNo, contact);
    }
    Does that look fine ..

    Code:
    Address Rental::ReadNewAddress(Address address)
    {
    	std::string fline, sline, sbb, city, cde;
    	
    	system("cls");
    
    	std::cout << "\n     \t\t\t&#201;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#187;\n";
    	std::cout << "     \t\t\t&#186;        PHYSICAL ADDRESS       &#186;\n";
    	std::cout << "     \t\t\t\314&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;&#205;\271";
    
    	std::cout << "\n\n\nEnter physical address below ...";
    	
    	std::cout << "\n\n1. First line : ";
    	std::cin >> fline;
    
    	std::cout << "\n2. Second line : ";
    	std::cin >> sline;
    
    	std::cout << "\n3. Third line : "; 
    	std::cin >> sbb;
    
    	std::cout << "\n4. City : ";
    	std::cin >> city;	
    	
    	std::cout << "\n5. Code : "; 
    	std::cin >> cde;
    	
    	address.SetAddress(fline, sline, sbb, city, cde);
    
    	return address;
    }
    Reason am asking is if i use a reference as 'void Rental::ReadNewAddress(const Address& address) then i cant set the address ... Hence opted for return address ...

  13. #58
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by csonx_p View Post
    Reason am asking is if i use a reference as 'void Rental::ReadNewAddress(const Address& address) then i cant set the address ... Hence opted for return address ...
    If you want to change the address, don't make it const.

  14. #59
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Wait. I thought we were going to have a ReadFromFile, which did a lot of >> type things, and a ReadFromUser, which was going to be the interactive input.
    Ah, I was not paying attention. In that case, ReadFromFile() should just be replaced by operator>> overloaded with respect to that class.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #60
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by matsp View Post
    Yes, that may be OK for many things, but for example:
    "return milage" - check that it's not LESS than the out-milage (if that is not checked, the "driven milage" may turn negative, and the customer gets a "discount" that wasn't really meant to be there.
    "registration number" - Should be a valid registration number - whatever that may be - varies from one country to another, and here in the UK there are at least 4 different variants: AA99AAA is the modern one, A9[99]AAA is the prior one, and before that it was AAA9[99]A. Before that AAA9[99] I think]. (A representing an alphabetic character - not Q O, or I in normal cases, although Q9[99]AAA is valid at the very least). I think Isle of Man and Northern Ireland uses different systems [or there is some special sequences of AAA that indicate those regions].

    "model year" - check that it's not more than +1 of the current year for example.

    "drivers licence number" - may need checking against valid ones.

    --
    Mats
    So Mats, what do you think of my validations ????

    Code:
    #ifndef VALID_H
    #define VALID_H
    
    #include <boost/regex.hpp>
    #include <string>
    #include <time.h>
    
    #define YR_OLD 2
    
    namespace valid
    {
    	/* Validate RSA ID number */
    	bool driverIDValidator(const std::string& id)
    	{
    		static const boost::regex e("^[0-9]{6}[0-9]{4}[0-9]{3}$");
    		return regex_match(id, e);
    	}
    
    	// Validate RSA land line number 
    	bool landLineValidator(const std::string& lndln)
    	{
    		static const boost::regex e("(0|\\+27)[1234][123][-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(lndln, e);
    	}
    
    	// Validate RSA cell/toll-free number 
    	bool cellNoValidator(const std::string& cn)
    	{
    		static const boost::regex e("(0|\\+27)[78]([01234]|[68])[-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(cn, e);
    	}
    
    	// Validate string not containing numbers 
    	bool stringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate string containing numbers 
    	bool mixedStringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z0-9  ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate RSA postal code 
    	bool postalCodeValidator(const std::string& c)
    	{
    		static const boost::regex e("^([0-9]{4})$");
    		return regex_match(c, e);
    	}
    
    	// Validate car engine size 
    	bool engineCapValidator(const std::string& c)
    	{
    		static const boost::regex e("^[0-9]{2}(00)$");
    		return regex_match(c, e);
    	}
    
    	// Validate RSA char/digit value
    	int charValidator(const char& c)
    	{
    		return isdigit(c); 
    	}
    
    	int rentalTypeValidator(const std::string& s)
    	{
    		return !( s.compare("Unlimited") && s.compare("200km") );
    	}
    	
    	bool yearModelValidator(const int& value)
    	{
    		time_t rawtime;
    		tm* timeinfo;
    
    		time( &rawtime );
    		timeinfo = localtime ( &rawtime );
    
    		int year = timeinfo->tm_year+1900;
    
    		if(value < year-YR_OLD && value > year)
    			return false;
    		else
    			return true;
    	}
    }
    Last edited by csonx_p; 09-11-2008 at 03:52 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. what design patter let me reuse this class?
    By patiobarbecue in forum C++ Programming
    Replies: 4
    Last Post: 04-29-2009, 01:44 PM
  2. reuse a socket connection
    By radeberger in forum Networking/Device Communication
    Replies: 0
    Last Post: 03-18-2009, 11:38 AM
  3. Deallocate Memory and reuse pointer
    By appleGuy in forum C++ Programming
    Replies: 9
    Last Post: 06-20-2007, 11:07 AM
  4. homework v.s. reuse
    By xddxogm3 in forum C++ Programming
    Replies: 2
    Last Post: 12-08-2003, 02:18 PM
  5. exceptions: reuse <stdexcept> classes???
    By Ruchikar in forum C++ Programming
    Replies: 5
    Last Post: 06-25-2002, 03:09 AM