Adding a member function to iostream?

Hello, I'm trying to write a function that will clear and ignore cin data with a single call. Is it possible to use cin.(insert function name) with the following code, without construction? For example cin.flush_cin(some_string_here)?

1
2
3
4
5
6
7
8
9
10
class Tflush : public iostream{
	private:
		template<typename T> void flush(T to_clear){
			cin.clear();
			cin.ignore(sizeof(to_clear));
		}
	public:
		inline void flush_cin(string to_flush){flush (to_flush);}
		inline void flush_cin(char to_flush){flush (to_flush);}
};
Last edited on
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <limits>

template < typename CHAR_TYPE, typename TRAITS_TYPE > // user-defined manipulator
inline std::basic_istream<CHAR_TYPE,TRAITS_TYPE>& clear_line( std::basic_istream<CHAR_TYPE,TRAITS_TYPE>& istm )
{
    istm.clear() ;
    return istm.ignore( std::numeric_limits<std::streamsize>::max(), TRAITS_TYPE::to_int_type( istm.widen('\n') ) ) ;
}


Usage example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    int i ;

    if( std::cin >> i ) std::cout << i << '\n' ;

    else
    {
        std::cerr << "error in input\n" ;

        std::cin >> clear_line >> i ; // clear the error, discard rest of line, and then read i

        std::cout << i << '\n' ;
    }
}


Last edited on
Is it possible to use cin.(insert function name) with the following code, ...

No. Or at least not easily.

cin already has a type. So while you could replace the standard cin with your custom version, your problem would be better handled by writing a utility function instead.

(Apart from anything, the class name flush is very poor. iostream_with_flush would at least same what it is and does. And flush() already has a meaning as defined by ostream::flush())

Then bear in mind that ignore() is actually a method of istream, not iostream (which inherits from ostream and istream) and that they are all actually template instantiations (of basic_istream<>, etc.)

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
#include <iostream>
#include <limits>
#include <string>
#include <sstream> // for testing
using namespace std;

template <class charT, class traits>
basic_istream<charT, traits>& clear_and_ignore(
    basic_istream<charT, traits>& is,
    size_t n = numeric_limits<streamsize>::max(),
    int delim = EOF) {
    is.clear();          // clear all stream error state flags
    is.ignore(n, delim); // ignore up to n chars stopping at delim
    return is;
}

int main() {
    const string color_name = "red";
    const string cost_name  = "cost";

    int    N = 0;
    string product;
    double cost = 0.0;

    // use stringstream for testing
    string testData = "99 red balloons cost $1.23";
    stringstream iss(testData);

    streambuf* cinbuf = cin.rdbuf(); // save old buffer
    cin.rdbuf(iss.rdbuf()); // redirect cin to iss

    // cin is reading from stringstream now, not console input
    cin >> N;
    // does what inline void flush_cin(string to_flush){flush to_flush;}
    // looks like it's intended to do?
    clear_and_ignore(iss, color_name.length() + 1); // space plus "red"
    cin >> product;
    clear_and_ignore(iss, cost_name.length() + 1); // etc
    // similarly for inline void flush_cin(char to_flush){flush to_flush;}
    clear_and_ignore(iss, 2);
    cin >> cost;

    cin.rdbuf(cinbuf); // restore old buffer

    cout << "N       = " << N       << "\n";
    cout << "product = " << product << "\n";
    cout << "cost    = " << cost    << "\n";

    return 0;
}


N       = 99
product = balloons
cost    = 1.23



But I am not sure how you want to use this functionality?

Andy
Last edited on
I'm using this to write a game for my class. I got sick of writing
1
2
3
4
if(condition){
    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


over and over. I knew that i'd need a template to do this, but I'm a bit of a noob at writing them. Our class hasn't learned them yet, so I'm jumping ahead a little.

Thanks for your answers, guys!
Last edited on
> I knew that i'd need a template to do this

If the functionality is required only for standard narrow input streams with default character traits, the manipulator need not be templated. This would suffice:
1
2
3
4
5
6
7
8
#include <iostream>
#include <limits>

inline std::istream& clear_line( std::istream& istm )
{
    istm.clear() ;
    return istm.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
}

Topic archived. No new replies allowed.