1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
#include <iostream>
#include <string>
#include <sstream>
#include <type_traits>
namespace detail
{
template < typename T > T& convert( const std::string& str, T& value, std::ios_base::fmtflags fmtflags )
{
std::istringstream stm(str) ;
stm.flags(fmtflags) ;
char c ;
if( stm >> value && stm >> std::skipws && !( stm >> c ) ) return value ;
else throw std::invalid_argument( "bad value" ) ;
}
// overload for std::string
std::string& convert( const std::string& str, std::string& value, std::ios_base::fmtflags )
{ return value = str ; }
// overload for const char*
// etc.
template < typename T >
typename std::enable_if< std::is_default_constructible<T>::value &&
std::is_move_constructible<T>::value, T >::type
convert( std::string str, std::ios_base::fmtflags fmtflags )
{
T value ;
return std::move( convert( str, value, fmtflags ) ) ;
}
}
template < typename T, typename CONDITION >
T& get_a_complete_line( const std::string& prompt, T& value, CONDITION&& cond ,
const std::string& err_str, std::istream& stm = std::cin )
{
{
std::string line ;
if( std::cout << prompt && std::getline( stm, line ) )
{
try
{
detail::convert( line, value, stm.flags() ) ;
if( std::forward<CONDITION>(cond)(value) ) return value ;
}
catch( const std::exception& ) {}
}
else throw std::runtime_error( "stream error" ) ;
}
std::cerr << err_str << '\n' ;
return get_a_complete_line( prompt, value, std::forward<CONDITION>(cond), err_str ) ;
}
template < typename T, typename CONDITION >
typename std::enable_if< std::is_default_constructible<T>::value &&
std::is_move_constructible<T>::value, T >::type
get_a_complete_line( const std::string& prompt, CONDITION&& cond ,
const std::string& err_str, std::istream& stm = std::cin )
{
T value ;
return std::move( get_a_complete_line( prompt, value, std::forward<CONDITION>(cond), err_str, stm ) );
}
int main ()
{
int number = get_a_complete_line<int>( "a number greater than 99 ? ", []( int v) { return v > 99 ; },
"badly formed input" ) ;
std::cout << "the number is: " << number << '\n' ;
std::cin >> std::hex ;
number = get_a_complete_line<int>( "an even integer in hex format ? ", []( int v) { return v%2 == 0 ; },
"you must be joking. please renter the value" ) ;
std::cout << "the number is: " << std::hex << number << '\n' ;
std::string str = get_a_complete_line<std::string>( "? ", []( std::string v) { return v.size() < 20 ; },
"string is too long" ) ;
std::cout << str << '\n' ;
}
|