I'm trying to learn a bit about templates and metafunctions, namely std::enable_if
. I'm making a menu system for our school assignments (extracurricular, mind you), and need a way of getting input from the user. I'd like to define a template class for various types of input - something used along the lines of:
std::string userInput = Input<std::string>("What's your name?").Show();
float userHeight = Input<float>("How tall are you?").Show();
I'd like to (and I'm sure there are reasons not to, but nevertheless) do this generalized sort of conversion using a std::stringstream
: get input from user, feed into SS, extract into variable of type T.
It's easy enough to see if the conversion failed during runtime, but I'd like to use std::enable_if
to prevent people from using my Input<>
class for cases where conversion is impossible, say:
std::vector<Boats> = Input<std::vector<>>("Example").Show();
Obviously a std::stringstream
cannot convert a string to a vector, so it will always fail.
Can I format an std::enable_if
clause to ONLY allow instantiation of my template class for the types listed above? Alternatively, is there a better way to go about it? Have I got things completely the wrong way around?
I believe I have found a list of allowed types that std::stringstream
can "convert" a string into:
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
I've been using std::enable_if
like this up until this point:
template <typename T, typename = typename
std::enable_if<std::is_arithmetic<T>::value, T>::type>
However, now I'd like to extend it to allow not only arithmetic values, but all values supported by the sstream >>
operator.
If you prefer to use a SFINAE with a class template parameter, then you want
template <
typename T,
typename = decltype(std::declval<std::istringstream &>() >> std::declval<T &>(), void())
>
class Input /*...*/