Operator overloading & output suppression

Hey guys! I have two questions:

1st Question: I have three different classes A, B, and C; and correspondingly overloaded the insertion stream operator(<<) for all three classes. Classes A and B each have objects of class C as private data members. I am seeking a scheme whereby the << operator behaves differently for class C objects when an object of class A is to be printed from when an object of class B is to be printed. In other words, I want to have one << operator function invoked for class C when the object in question is of class A and another << operator function called for class C when the object in question is of class B. Is this realizable?

2nd Question: I have a derived class that uses a search function defined in an 'inaccessible' linked-list base class. By inaccessible, I mean I cannot change the contents of any of the member functions of this base class. The search function has three cout statements that print string literals showing results of the search operation if:
a. list is empty
b. search item is found in the list
c. search item is not found in the list upon searching

I am seeking a scheme whereby, instead of displaying the results of the search operation on the standard output (i.e. screen), a function I write can capture these string literals as input parameters, and process them for a Boolean value return. Is it possible to preclude the printing of the literals on the screen in this manner?
You could just redefine the operator<< for each class that you contain, and simply print out values obtained from their in-class C object, rather than using a prebuild operator for them.
I am sorry I do not get the drift of your post!

You could just redefine the operator<< for each class that you contain, and simply print out values obtained from their in-class C object, ...

If what you're saying is that I can redefine the << operator for classes A and B, well yeah, I have already done that to suit the program I'm writing. However, the << operator for class C is pretty much set in stone because I have used it in several other functional programs with its current definition; and, I do not want to change it. I know the flexibility I have is with classes A and B's overloaded << operators; however, the fact that both classes work in conjunction with a linked-list base class, with member functions that are not to be changed, ties my hand somewhat!


...rather than using a prebuild operator for them.

The data members of classes A and B are still going to be printed according to the overloaded << operator function for class C anyway. I'm not sure if that is what you're referring to.
> I want to have one << operator function invoked for class C when the object in question is of class A
> and another << operator function called for class C when the object in question is of class B.
> Is this realizable?

For that, the operator<< needs to be overloaded; for overloading to be possible, the types of the objects in the two overloads have to be different in some way.
For instance, we could create a type 'wrapped C' which looks and works like 'C', except for the overloaded operator:

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
#include <iostream>

struct C { C( int i = 6 ) : v(i) {} int v ; /* .... */ };
std::ostream& operator<< ( std::ostream& stm, const C& c )
{ return stm << "object of type C {" << c.v << '}' ;  }

struct A
{
    // ...
    A() : c(20) {}

    struct sub_object_C : C
    {
        using C::C ; // inherit constructors
        friend std::ostream& operator<< ( std::ostream& stm, const sub_object_C& c )
        { return stm << "wrapped sub-object of type C{" << c.v << '}' ;  }
    };

    int i = 234 ;

    sub_object_C c;
};

std::ostream& operator<< ( std::ostream& stm, const A& a )
{ return stm << "A { " << a.i << ", " << a.c << " }" ;  }

int main()
{
    C c ;
    std::cout << "stand-alone => " << c << '\n' ;

    A a ;
    a.c.v += 10 ;
    std::cout << "contained in A => " << a.c << '\n' ;
    std::cout << "A => " << a << '\n' ;

    C& cc = a.c ;
    std::cout << "un-wrapped => " << cc << '\n' ;
}

http://coliru.stacked-crooked.com/a/bc7960cb35ced17a



> capture these string literals as input parameters, and process them for a Boolean value return.
> Is it possible to preclude the printing of the literals on the screen in this manner?

Yes. By replacing the streambuf associated with std::cout with our own std::stringbuf. This will redirect the output to the stringbuf.

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
#include <iostream>
#include <sstream>

void foo( int a )
{
    std::cout << "output to stdout from function foo: " << a*a << '\n' ;
}

struct redirect_to_string // non-copyable
{
    explicit redirect_to_string( std::ostream& s ) : stm(s), oldbuf( stm.rdbuf( &buf ) ) {}
    ~redirect_to_string() { stm.rdbuf( oldbuf ) ; }

    std::string str() const { return buf.str() ; }

    redirect_to_string( const redirect_to_string& ) = delete ;
    redirect_to_string& operator= ( const redirect_to_string& ) = delete ;

    std::stringbuf buf { std::ios_base::out } ;
    std::ostream& stm ;
    std::streambuf* oldbuf ;
};

int main()
{
    // capture output of foo to a string
    std::string str ;
    {
        redirect_to_string rts(std::cout) ; // redirect output to stringbuf
        foo(23) ; // call foo; output from foo goes to the stringbuf
        str = rts.str() ; // copy contents from he stringbuf into our string
        str.pop_back() ; // remove the new-line at the end (if required)
        // note: destructor of rts will restore the original streambuf
    }

    std::cout << "string contains: '" << str << "'\n" ;
}

http://coliru.stacked-crooked.com/a/fbef1328453388bb
@ JLBorges:

Thanks indeed for your post! It is very heartwarming that my seemingly quixotic requests are possible within the realm of C++; it is heartbreaking however that I do not fully understand the codes you provided: especially the second solution - about one-third of which is above my pay grade. I'd really have to read up on that one and would ask any questions I have later.

The first code I follow for the most part but would appreciate it if you could explain what the colon in these lines/constructs do (I'm still learning C++):

3 struct C { C( int i = 6 ) : v(i) {} int v ; /* .... */ };

10 A() : c(20) {}

I understand what is happening on either side of the colon in each statement; however, what does the colon signify?


Finally, why is the following statement needed?

14 using C::C ; // inherit constructors

when I thought the constructor(s) from class C should have been implicitly inherited through the statement:

12 struct sub_object_C : C

Eagerly awaiting your reply. Please, if you have any links to useful/relevant online literature, providing them would be appreciated. Thx.
Last edited on
> explain what the colon in these lines/constructs do (I'm still learning C++):
> struct C { C( int i = 6 ) : v(i) {} int v ; /* .... */ };
> A() : c(20) {}

The respective constructors are using member initializer lists t initialize the members.
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr388.htm

Line 19 in the first snippet int i = 234 ; is an in-class member initializer.
http://www.stroustrup.com/C++11FAQ.html#member-init


> Finally, why is the following statement needed?
> using C::C ; // inherit constructors

In struct sub_object_C : C, we want sub_object_C to be usable exactly like a C; we want it to be constructible exactly like a C; and inherited constructors provide a succinct way of saying that 'an object of this derived class can be constructed using the syntax and semantics of any of the constructors present in the base class'
http://www.stroustrup.com/C++11FAQ.html#inheriting



> I do not fully understand the codes you provided: especially the second solution

The C++ stream library is an extremely flexible library; primarily this flexibility comes from separation of different concerns into different components, with the facility to mix and match these components as required.

Every stream has an associated stream buffer; the stream buffer is responsible for in-memory buffering of characters that are input/output, and transporting these characters from/to an actual physical target like a file. We can replace the stream buffer associated with a stream with another stream buffer when we want to redirect output elsewhere.
http://www.cplusplus.com/reference/ios/ios/rdbuf/

std::cout is an output stream, by default it is associated with a custom stream buffer that sends the output characters to stdout. std::stringbuf is another kind of stream buffer; it sends the output characters to a string held in memory.
http://www.cplusplus.com/reference/sstream/stringbuf/
(Needless to say, std::filebuf is yet another kind of stream buffer which sends the output to a file.)

What we are doing is:
a. replace the stream buffer associated with std::cout with a std::stringbuf
b. save the original stream buffer (we want to restore it at the end)
c. call the function(s) which perform output with std::cout
d. the actual output to std::cout is written via the std::stringbuf
e. copy that output from the stringbuf into a string of out own
f. finally, restore the original stream buffer asociated with std::cout.

Things get messy if an exception is thrown, somewhere in between steps a. and f.; we are C++ programmers, so we use RAII. We wrap the whole sequence to between the constructor and the destructor of the shim class redirect_to_string, and our code automagically becomes exception safe.

Streambuf tutorial: http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
Topic archived. No new replies allowed.