I've never seen this sort of thing before. What is this called?Code:[&](const Beer& beer) -> bool { return goodBeers.find(beer) != goodBeers.end(); }
I've never seen this sort of thing before. What is this called?Code:[&](const Beer& beer) -> bool { return goodBeers.find(beer) != goodBeers.end(); }
"If you tell the truth, you don't have to remember anything"
-Mark Twain
They are called lambdas. They will come with C++0x.
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).
Oh yes, I suppose this one is, but a generic solution would take const T&.The type signature. It says "int" right there.
Not a big problem, though.
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?
No, boost format overloads the % operator for the "variadic arguments". You can do things like:
However, it doesn't return a std::string or a const char* but some boost's type.Code:std::cout << boost::format("...") % a % b << '\n';
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.
Quoted more than 1000 times (I hope).Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
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:
How do I make this possible with functions in the most efficient way?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;
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...
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...)
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.
Quoted more than 1000 times (I hope).Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
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) )
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.)
SomaCode: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) ) );
Last edited by phantomotap; 02-12-2009 at 04:12 PM. Reason: broke long source line
A few construction overloads for what, exactly?
It should not rely on one compiler... if it does, then it's a bug.You need to cleanup the source to remove the reliance on specific compilers. (I can't check my assumptions for sure.)
Ah, but I can't be bothered to check with gcc >_<
That's a cool suggestion actually. Certainly, that's easy and feasible.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.)
I can do that as above.You should have an overload with a "get input" parameter. (I can then pass expressions such as 'cin_ >> _string' or 'wcin_ >> _line' as arguments.)
The question is - what warnings and what empty return statements?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.)
In those functions where I do a conditional check with if and return true/false?
*shrug*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.)
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.
Overloads of 'Read' to be used/passed to constructors--or any other function. [1]->[2]A few construction overloads for what, exactly?
You aren't worth helping if you can't bother to search your own source for 'return;'.The question is - what warnings and what empty return statements?
It is, but that isn't important.I wanted a powerful [...] specialization is not enough.
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.Thus, the only way [...] a specific class/function entirely.
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...Noone was kind enough to explain how this would be possible with functions only.
Soma
Code:type x; Read(x, ?, ?, ?, ?);Code:type x(Read<type>(?, ?, ?, ?));
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.You aren't worth helping if you can't bother to search your own source for 'return;'.
Reserved for further update when I have time to properly read through and type a reply...