Click to See Complete Forum and Search --> : Overloaded output stream with custom namespace


dlite922
03-21-2007, 02:02 AM
The problem is a little complex for me:

SETUP:
--------------------------------------------------
main.cpp // driver program
vector.h // contains two functions that each declare a vector (one for integer, and one of my Book object defined in book.h)
print.hpp // template class that prints any stl container type, (list,queue,stack,vector etc.
book.h // my class of a few functions that store a few string of book info and overloaded output input stream operator defined. (I'm only concerned with output in this program)

WHAT I'M TRYING TO DO:
---------------------------------------------------
i'll have future files like vectors.h for stacks.h, queues.h to basically explore the stl container types. :p i need to use a template class (print.hpp) with a Book object. (works fine with integer) ie print::dislplay(v) //if v is vector or ints works fine, but not if its of type Book.

The ERROR:
------------------------------------
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const Book' (or there is no acceptable conversion)

i've included book.h in print.hpp and/or/xor vector.h at no avail.

tried defining the overload in print.hpp and adding it as friend, didn't like it.

MY QUESTION:
------------------------------------
obviously, how can I print of type book. how do i tell print.hpp to use the overloaded book.h's output stream operator? tried making print.hpp a friend in book.h

I'M COMPLETELY LOST, this is kinda beyond my realm!!!



MY CODES:
---------------------------------------------------
////////// tips.hpp

#ifndef PRINT_HPP
#define PRINT_HPP

#include <iostream>

namespace print
{

// Display on one line of cout each element of a container
// text - optional text to display before the elements
// (if there is text it will be followed by a colon and a space)
// element_separator - character(s) to put between the elements
// (default is a space)

template <class T>
void display( const T& container, const char* text=0, const char* element_separator = " " )
{
const char* text_separator = ": ";

// if there's text, display it and some separator characters
if( text != 0 )
std::cout << text << text_separator;

// store the end iterator, which doesn't change
typename T::const_iterator container_end = container.end();

// display each element followed by the element separator
for( typename T::const_iterator i = container.begin();
i != container_end; ++i )
std::cout << *i << element_separator; // ***WHERE ERROR POINTS TO***

std::cout << std::endl;
}

} // end namespace
#endif







////////// book.h
// just the part we're concerned with.

class Book
{
friend ostream &operator<<( ostream &, Book &);
public:
....// etc.
private:
....// etc.
}
.
.
.
ostream &operator<<( ostream &output, Book &b)
{
output.setf(ios::fixed);
output
//<< setw(4)
//<< right
//<< b.book_idkey
<< right << " $" << setw(5) << setprecision(2) << b.book_cost
//<< " " << setw(12) << left << b.getGenre()
//<< setw(18) << b.book_isbn
<< " " << left << setw(34) << b.book_author
<< b.book_title;


return output;

}


//////////vector.h

.
.
.
void myBookVector()
{
system("cls");

cout << "\n\t\tBOOK VECTOR";

vector<Book> v;

cout << "\n\n2a. NOW INSERTING A BOOK...";
v.push_back(Book(203,"0-553-29651-X","Hooper, Johansen, Preston","The Delaney Christmas Carol",7.50,ANTHOLOGY));

cout << "BOOK INSERTED!\n\n2b. THE VECTOR NOW CONTAINS:\n";

//2b. Display the vector.
tips::display(v); // <<<<<< DOESN'T LIKE THIS!! *********



yes this output stream works fine and has been tested.

thanks for your help in advance, i hope i've made my question clear enough, just in case i've missed something let me know.

Danny
03-21-2007, 05:08 AM
Are you by any chance using Visual C++ 6.0?

dlite922
03-21-2007, 05:09 AM
Visual Express 2005

its free! ? :D

jonnin
03-21-2007, 08:39 AM
visual, even the newer ones, sometimes confuses the << output operator with the binary "shift" operator (same syntax, different usage) -- a simple cast operation will often clear this up.

dlite922
03-21-2007, 10:59 PM
figured it out. it was a matter of the iterator being a constant one, and my overloaded operator was not declared as const. change either, and works.

dang const! c++ should be less strict (ie convert something not const to const, not vice versa)

thanks for all your help! (just joined the community for this question, i hope i can be a postive contributor)

dlite922
03-21-2007, 11:00 PM
solution if anybody is having this same problem (if not obvious by description above)

change
ostream &operator<<( ostream &output, Book &b)

to
ostream &operator<<( ostream &output, Book &b) const

Danny
03-22-2007, 02:10 AM
Actually, my advice is to declare the overloaded stream operators as extern functions, not as class members. This will also save you the trouble of having to declare the member function as const. Additionally, I think you want to declare the Book & book argument as const, too:
ostream &operator<<( ostream &output, const Book &b);

dlite922
03-22-2007, 02:18 AM
their "external" just befriended (see book.h above)

as for your advice to make more things const :shrug: , i know the benefits, and when possible, i'll stay away unless i need to. they seem to cause newbies headaches.

thanks!