First of all, thank you so much for all of this help, it's really helping me understand all of this.
Second, I did a lot more looking into it and reading, and I think I came up with something (closely related to your ignore and pause classes as I looked at those quite a bit).
template <typename CharT>
std::streamsize ignore_line( std::basic_istream<CharT> &in, bool always_ignore= false )
{
std::streamsize nread= 0;
in.clear();
if( always_ignore || ( in.rdbuf()->sungetc() != std::char_traits<CharT>::eof() && in.get() != '\n' ) )
{
in.ignore( std::numeric_limits<std::streamsize>::max(), in.widen('\n') );
nread= in.gcount();
}
in.clear();
return nread;
}
template <typename var_type>
class extract
{
var_type *var;
bool _always_flush, _full_count;
mutable std::streamsize *_nread;
public:
extract( var_type &input, bool always_flush= false )
: _always_flush(always_flush), _nread(0), var(&input), _full_count(false)
{}
extract( var_type &input, std::streamsize &nread, bool always_flush= false )
: _always_flush(always_flush), _nread(&nread), var(&input), _full_count(false)
{*_nread=0;}
//_nread[0] holds pre-extraction character ignore count
//_nread[1] holds mid-extraction character ignore count
//_nread[2] holds post-extraction character ignore count
extract( var_type &input, std::streamsize nread[3], bool always_flush= false )
: _always_flush(always_flush), _nread(nread), var(&input), _full_count(true)
{_nread[0]=0;_nread[1]=0;_nread[2]=0;}
template <typename CharT>
friend std::basic_istream<CharT> &operator>> ( std::basic_istream<CharT> &in, const extract &manip )
{
int _ignore_count= 0;
if( manip._always_flush || !in )
manip._nread[0]+=ignore_line(in);
in >> *manip.var;
while(!in)
{
cout << "\nInvalid data type, please enter a value of type: "
<< typeid(*manip.var).name() << "\n-> ";
_ignore_count+= ignore_line(in, true);
in >> *manip.var;
}
if(manip._full_count)
{
manip._nread[1]= _ignore_count;
_ignore_count= 0;
}
if(manip._always_flush)
_ignore_count+= *manip._nread= ignore_line(in);
if(manip._full_count)
manip._nread[2]= _ignore_count;
return in;
}
};
void main()
{
int i;
char c;
string s;
std::streamsize chars[3];
cout << "char? ";
cin >> extract<char>(c);
cout << "char: " << c << endl;
cout << "int? ";
cin >> extract<int>(i, chars, true);
cout << "int: " << i << endl << "ignored: " << chars[0] << ' ' << chars[1] << ' ' << chars[2] << endl;
cout << "string? ";
cin >> extract<string>(s);
cout << "string: " << s << endl;
}
It works well, although, I am unsure about the parts involving _nread. If there is a better way to do this, please let me know. Also, whenever I enter "asdf" for the first input, the first ignore count comes out to be 1 when it seems to me that it should be 4 (ignoring 'sdf\n'). Again, thank you so much for all of this, I think I'm understanding all of these concepts quite a bit better now.