Thread: Input class project (again)

  1. #31
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    937
    Code:
    [&](const Beer& beer) -> bool { return goodBeers.find(beer) != goodBeers.end(); }
    I've never seen this sort of thing before. What is this called?
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    They are called lambdas. They will come with C++0x.

    Quote Originally Posted by CornedBee View Post
    Argument-dependent lookup.
    How? What additional parameters would such a function take? It would be identical, or should be, so the compiler can neither overload nor call those functions unless it is designed for to take a specific given type, which is must not necessarily be (you should be able to create a generic function that takes all kinds of types, but reads differently).

    The type signature. It says "int" right there.
    Oh yes, I suppose this one is, but a generic solution would take const T&.
    Not a big problem, though.

    Quote Originally Posted by anon View Post
    Another technical problem trying to overcome the repetion of values 10 and 20

    Code:
    template <class T>
    class ValidateRangeT
    {
        T lower, upper;
    public:
        ValidateRangeT(const T& lower, const T& upper): lower(lower), upper(upper) {}
        bool operator () (const T& value) const
        {
            return value > lower && value < upper;
        }
    };
    
    template <class T>
    ValidateRangeT<T> ValidateRange(const T& low, const T& high)
    {
        return ValidateRangeT<T>(low, high);
    }
    
    
    int main()
    {
    	int x;
    	int low = 10;
    	int high = 20;
    	Input::Read<int, std::string>(
    	    x,
                "Enter an integer: ",
                "That is not a valid integer. Try again.",
                boost::str(boost::format("The integer must be bigger than %d and lower than %d.") % low % high),
                ValidateRange(low, high)
            );
    	std::cout << "You entered: " << x << std::endl;
    }
    I have to go to some lengths because you assume that all the messages will be of the same type. (This may also be the reason why you "needed" the const char* version.)

    Ideally I should be able to write the following (since boost::format overloads operator<<)

    Code:
    int main()
    {
    	int x;
    	int low = 10;
    	int high = 20;
    	Input::Read(
    	    x,
                "Enter an integer: ",
                "That is not a valid integer. Try again.",
                boost::format("The integer must be bigger than %d and lower than %d.") << low << high,
                ValidateRange(low, high)
            );
    	std::cout << "You entered: " << x << std::endl;
    }
    You mean like that (corrections in red)?
    I didn't know about boost::format, but I can see where it comes from and I would say it is very handy.
    Still, doing it this way also eliminates the need for the class, which might be even better?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #33
    The larch
    Join Date
    May 2006
    Posts
    3,573
    No, boost format overloads the % operator for the "variadic arguments". You can do things like:
    Code:
    std::cout << boost::format("...") % a % b << '\n';
    However, it doesn't return a std::string or a const char* but some boost's type.

    Since the messages can come from different places, perhaps you shouldn't assume that these are all of the same type:

    Code:
    	template<typename DataT, typename StringT>
    	void Read(DataT& Out, const StringT Question, const StringT ErrorType, const StringT ErrorValidation)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #34
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Of course, you meant that the boost type could be passed to cout, since it supports the << operator... I see.
    I suppose I could use different types for all the strings, too. Good idea.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #35
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I added some improvements to the code.
    But I have three questions:
    1)

    class Range
    class Min: private Range
    class Max: private Range

    Is private inheritance the right thing here? I don't think public inheritance is right since it is not an "is-a" relationship...? Still, they practically share the same code base, so...

    2) These validation classes... currently they take int as argument, but I don't think that's good if you want to use bigger integers, not to mention unsigned. Should they take template parameters with the type? If they do that, I'd have to explicitly mention the type, which I'm looking to avoid...

    3) The most important of all. Say I want one version of the function to read using std::getline and one to use std::cin, how do I make this possible, without duplicating code or making new functions for all of them?
    I would rather be able to call both of them at the same time, as well, so modifying the original function is out of the question.
    For example:

    Code:
    	int x, y;
    	const int Max = 20;
    	const int Min = 10;
    	Input::ReadWithStdGetLine
    	(
    		x,
    		"Enter an integer: ",
    		"That is not a valid integer. Try again.",
    		boost::format("The integer must be bigger than %d and lower than %d.") % Min % Max,
    		Input::Validate::Max(Max)
    	);
    	Input::ReadWithStdCin
    	(
    		x,
    		"Enter an integer: ",
    		"That is not a valid integer. Try again.",
    		boost::format("The integer must be bigger than %d and lower than %d.") % Min % Max,
    		Input::Validate::Max(Max)
    	);
    	std::cout << "You entered: " << x << " and " << y << std::endl;
    How do I make this possible with functions in the most efficient way?

    And why do I attach the source, you ask?
    Because then I don't have to wrap the lines so you don't have to scroll on the board...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #36
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I made another prototype design.
    This one couples the flexibility of classes along with functions.
    I cannot say if it's any good idea or not. And I'm still missing things that I would like, such as determining what stream to output to, etc.

    Please, please, PLEASE tell me what you think?
    (Note the hackish solution for boost::bind, as well, in the class's ReadData function. I used it so I could pass a temporary boost::bind object to it, since I have NO idea what type boost::bind returns. Guess I'll have to wait for C++0x's auto and move references to remove that hackish solution...)
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #37
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If you want to know what (a particular) bind returns just try to assign it to something, e.g int and then copy the name of the type from the compiler error message (Cannot convert xyz to int)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  8. #38
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Dang, that type is excessive, but yes I did it... I did manage to do it.
    Guess I was just too tired from fighting with the compiler to do it before...

    Code:
    		DataT (*temp_convert)(const std::string&) = &boost::lexical_cast<DataT>;
    		boost::_bi::bind_t
    		<
    			void,
    			boost::_mfi::mf1<void, Input::CInput<std::string>, std::string&>,
    			boost::_bi::list2
    			<
    				boost::_bi::value< Input::CInput<std::string> >, boost::arg<1>
    			>
    		>
    		temp_bind = boost::bind(&Input::CInput<std::string>::ReadFunction, InputClass, _1);
    
    		for (;;)
    		{
    			std::cout << Question;
    			if ( InputClass.ReadDataEx(ConvertedInput, temp_bind, temp_convert) )
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #39
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I don't have 'Boost' installed, so I can't play this much, but I do have some suggestions and opinions:

    You should provide a few construction overloads. (Overloads that return a valid instance of the result type in the given range.)

    You need to cleanup the source to remove the reliance on specific compilers. (I can't check my assumptions for sure.)

    You should use traits to determine if the parameters are "string-likes" or, say, parameterless function objects. (I can then do clever things like passing 'cout_ << "whatever"' as an argument for the 'Question' parameter.)

    You should have an overload with a "get input" parameter. (I can then pass expressions such as 'cin_ >> _string' or 'wcin_ >> _line' as arguments.)

    If you provide a few "probably mutator" methods or a few simple functions you can eliminate a few compiler warnings. (For example, many compilers will not like the empty return statement.)

    And, as usual, your prejudice for "OOP" has lead to a design that requires you to write additional code to make it functional. (If more of the design was simple functions it would be a bit less work.)

    Code:
    int x(
       marshal_input<int>(
          cin_ >> _line,
          cout_ << "Enter an integer: ",
          cout_ << "That is not a valid integer. Try again.",
          cout_ << (boost::format("The integer must be bigger than %d and lower than %d.") % Min % Max),
          Input::Validate::Range(Min, Max)
       )
    );
    Soma
    Last edited by phantomotap; 02-12-2009 at 04:12 PM. Reason: broke long source line

  10. #40
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    You should provide a few construction overloads. (Overloads that return a valid instance of the result type in the given range.)
    A few construction overloads for what, exactly?

    You need to cleanup the source to remove the reliance on specific compilers. (I can't check my assumptions for sure.)
    It should not rely on one compiler... if it does, then it's a bug.
    Ah, but I can't be bothered to check with gcc >_<

    You should use traits to determine if the parameters are "string-likes" or, say, parameterless function objects. (I can then do clever things like passing 'cout_ << "whatever"' as an argument for the 'Question' parameter.)
    That's a cool suggestion actually. Certainly, that's easy and feasible.

    You should have an overload with a "get input" parameter. (I can then pass expressions such as 'cin_ >> _string' or 'wcin_ >> _line' as arguments.)
    I can do that as above.

    If you provide a few "probably mutator" methods or a few simple functions you can eliminate a few compiler warnings. (For example, many compilers will not like the empty return statement.)
    The question is - what warnings and what empty return statements?
    In those functions where I do a conditional check with if and return true/false?

    And, as usual, your prejudice for "OOP" has lead to a design that requires you to write additional code to make it functional. (If more of the design was simple functions it would be a bit less work.)
    *shrug*
    I wanted a powerful input and be able to easily override functionality with my own, and not only for a specific type, so template specialization is not enough.
    Thus, the only way I know to do so is to make a base class and virtual functions or just choose a specific class/function entirely.
    Noone was kind enough to explain how this would be possible with functions only.
    If you would see point #3 in post #35. It it can be done with functions, then I would love to comply.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #41
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    A few construction overloads for what, exactly?
    Overloads of 'Read' to be used/passed to constructors--or any other function. [1]->[2]

    The question is - what warnings and what empty return statements?
    You aren't worth helping if you can't bother to search your own source for 'return;'.

    I wanted a powerful [...] specialization is not enough.
    It is, but that isn't important.

    Thus, the only way [...] a specific class/function entirely.
    You have used a specific instance of a specific expansion of a specific template class in the implementation for your interface. The only member variables are members of the 'Range' class which happens to be the only portion of the source that needs to be a class. The 'Range' class isn't instantiated as part of the interface. Everything used in the implementation of your 'Read' utility can be a simple function or a static method of a class. With this approach none of the kludge with 'bind' would be needed because you wouldn't need 'bind' at all.

    If you later need to expand a template based on the types involved, further separation of the interface from the implementation, possible forwarding to a static method of a template class, allowing for simple partial specialization, will let you choose the most appropriate implementation based on the types passed to the interface without complicating the implementation with pointless "OOP" or otherwise pointless expansions.

    Noone was kind enough to explain how this would be possible with functions only.
    Stand further back...

    Soma

    Code:
    type x;
    Read(x, ?, ?, ?, ?);
    Code:
    type x(Read<type>(?, ?, ?, ?));

  12. #42
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You aren't worth helping if you can't bother to search your own source for 'return;'.
    I was merely asking for what warnings. Yes, there is one empty return, but why should a compiler complain about that? It returns from a void function.

    Quote Originally Posted by phantomotap View Post
    Overloads of 'Read' to be used/passed to constructors--or any other function. [1]->[2]

    It is, but that isn't important.

    You have used a specific instance of a specific expansion of a specific template class in the implementation for your interface. The only member variables are members of the 'Range' class which happens to be the only portion of the source that needs to be a class. The 'Range' class isn't instantiated as part of the interface. Everything used in the implementation of your 'Read' utility can be a simple function or a static method of a class. With this approach none of the kludge with 'bind' would be needed because you wouldn't need 'bind' at all.

    If you later need to expand a template based on the types involved, further separation of the interface from the implementation, possible forwarding to a static method of a template class, allowing for simple partial specialization, will let you choose the most appropriate implementation based on the types passed to the interface without complicating the implementation with pointless "OOP" or otherwise pointless expansions.

    Stand further back...

    Soma

    Code:
    type x;
    Read(x, ?, ?, ?, ?);
    Code:
    type x(Read<type>(?, ?, ?, ?));
    Reserved for further update when I have time to properly read through and type a reply...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Trouble with a lab
    By michael- in forum C Programming
    Replies: 18
    Last Post: 12-06-2005, 11:28 PM
  4. Creating class object from user input?
    By Munkey01 in forum C++ Programming
    Replies: 8
    Last Post: 01-05-2003, 10:09 AM
  5. My final project for programming class...
    By Leeman_s in forum C++ Programming
    Replies: 3
    Last Post: 12-20-2001, 04:34 PM