views:

792

answers:

4

How can I overload the operator <<. The purpose of the overloaded operator is to do: cout << ptr->info and not receive the memory address but Display the maker year and model of that node's info section.

Example:

template <class DataType>
struct Node {
DataType info;
Node<DataType> *next;
};

In each info section of the Node there will be a struct like this:

struct Car {
    string maker;
    string year;
    string model;
}

So far I have this but it doesn't seems to work:

friend ostream &operator << ( ostream &output, Node<DataType> &rlist ) { //Overloaded <<
    output << rlist->info.make << endl;
    output << rlist->info.year << endl;
    output << rlist->info.price << endl; 

    return output;
}

When I compile with g++ I get this error:

LinkedList.cpp: In member function ‘void LinkedList<DataType>::EscribaUltimo() [with DataType = CarType]’:
main.cpp:37:   instantiated from here
LinkedList.cpp:15: error: no match for ‘operator<<’ in ‘std::cout << ptr->Node<CarType>::info’
+1  A: 

Just to make sure, you have

template<class DataType>

before the operator definition, right? If I do that, it works for me. The error messages show the line numbers in your code, but where is it in the pasted definitions? Reading it, I think the problem isn't with

Node<DataType> myNode;
output << myNode

but with

output << myNode.info

which does not have a operator<< defined for it.

Edit: By your comment, it sounds like you want to define an << operator for the car. So, I would do (untested)

ostream& operator<< (ostream& output, Car& car) {
  output << car.foo << end;
  output << car.bar << end;
  return output;
}

template <class DataType>
ostream& operator<< (ostream& output, Node<DataType>& node ) {
  output << node.info << end;
  return output;
}

Basically, what that means is that when you specialize your Node type and wish to use the << operator on it, you need to make sure that the DataType you are specializing with also has the << operator defined.

bsdfish
I Don't know how to define an operator << for myNode.info. That is exactly what I want to do.
LoKi
I find it surprising that it worked for you, given Naveen's (correct) remarks about errors in the accesses to Car, plus that the given operator is, at best, a specialization of a template for Car. Did you *actually* get output, or did it merely compile?
Martin v. Löwis
Martin, what is there to work? There isn't even a main function. What I meant was that I took the code Loki provided and got something similar to work. Sorry for not being precise.
bsdfish
It's still not clear to me what it is that you got to work (in particular if it's not your /untested/ code). However, it must deviate from the original code in more aspects than just adding the missing template declaration to the operator.
Martin v. Löwis
A: 

You need two operators: one for Node (or Node*), and one for Car:

ostream &operator << ( ostream &output, Car &car ) {
    output << car.maker << endl;
    output << car.year << endl;
    output << car.model << endl; 
    return output;
}

template<class DataType>
ostream &operator << ( ostream &output, Node<DataType> *rlist ) {
    output << rlist->info;
    return output;
}
Martin v. Löwis
+2  A: 

Although I'm a bit confused, because you're actual main code is missing. I'm going to assume you have a node, from traversing the link, and now want to print it:

#include <iostream>
#include <string>

using namespace std; // not recommended, but useful
                     // in snippets

// T is usually used, but this is of course up to you
template <class T> 
struct Node
{
    typedef T value_type; // a usual typedef

    value_type info;
    Node<value_type> *next;
};

struct Car
{
    string maker;
    string year;
    string model;
}; // you had a missing ;, probably copy-paste error

// this creates a node. normally you'd want this to be
// wrapped into a list class (more on this later)
template <typename T>
Node<T> *createNode(const T& info = T())
{
    // allocate node
    Node<T> *result = new Node<T>;
    result->info = info;
    result->next = 0; // no next

    return result; // returning a pointer means
                   // whoever gets this is
                   // responsible for deleting it!
}

// this is the output function for a node
template <typename T>
std::ostream& operator<<(std::ostream& sink, const Node<T>& node)
{
    // note that we cannot assume what node contains!
    // rather, stream the info attached to the node
    // to the ostream:
    sink << node.info;

    return sink;
}

// this is the output function for a car
std::ostream& operator<<(std::ostream& sink, const Car& car)
{
    // print out car info
    sink << "Make: " << car.maker <<
            "\nYear: " << car.year <<
            "\nModel: " << car.model << std::endl;

    return sink;
}

int main(void)
{
    // a car list
    typedef Node<Car> CarList;

    // a couple cars
    Car car1 = {"Dodge", "2001", "Stratus"};
    Car car2 = {"GMan's Awesome Car Company", "The future", "The best"};

    CarList *head = createNode(car1); // create the first node
    head->next = createNode(car2);

    // now traverse the list
    CarList *iter = head;
    for (; iter != 0; iter = iter->next)
    {
        // output, dereference iterator to get the actual node
        std::cout << "Car: " << *iter << std::endl;
    }

    // dont forget to delete!
    iter = head;
    while (iter)
    {
        // store next
        CarList *next = iter->next;

        // delete and move on
        delete iter;
        iter = next;
    }
}

Now, if you don't have to create your own linked list, use the standard link list instead, it simplifies your task immensely:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
#include <string>

using namespace std;

struct Car
{
    string maker;
    string year;
    string model;
};


// this is the output function for a car
std::ostream& operator<<(std::ostream& sink, const Car& car)
{
    // print out car info
    sink << "Make: " << car.maker <<
            "\nYear: " << car.year <<
            "\nModel: " << car.model << std::endl;

    return sink;
}

int main(void)
{
    // a car list
    typedef std::list<Car> CarList;

    // a couple cars
    Car car1 = {"Dodge", "2001", "Stratus"};
    Car car2 = {"GMan's Awesome Car Company", "The future", "The best"};

    CarList cars;
    cars.push_back(car1);
    cars.push_back(car2);

    // now traverse the list (copy to ostream)
    std::copy(cars.begin(), cars.end(),
             std::ostream_iterator<Car>(std::cout,"\n"));

    // delete done automatically in destructor
}

Hope this helps.

GMan
A: 

This is part, just the part that I want to overload the << operator. Let's hope this makes things clear:

LinkedList.h: #include using namespace std;

template <class DataType>    
struct Node {
DataType info;

Node<DataType> *next;

};

    template <class DataType>        
    class LinkedList

{

public: void EscribaUltimo(); friend ostream &operator << ( ostream &output, Node &rlist ) { //Overloaded <<

    output << rlist.make << endl;
    output << rlist.year << endl;
    output << rlist.price << endl; 

    return output;
    }

    //There is a method to insert from the front
    private:

Node<DataType> *start;

    Node<DataType> *current;              
inline void deepCopy( const LinkedList<DataType> & original );

};

LinkedList.cpp:

include

using namespace std;

template void LinkedList::EscribaUltimo() {

   if (start == NULL) { cout << "Empty List." << endl; }

   else {
   Node<DataType> *ptr = start;
   while (ptr != NULL) { cout << ptr->info << endl; ptr = ptr->next; }

   }

}

main.cpp:

include

include "LinkedList.h"

using namespace std;

struct CarType {

string maker;

int year;

float price;

};

int main() { CarType MyCar, YourCar; MyCar.maker = "Mercedes"; MyCar.year = 2002; MyCar.price = 20000;

YourCar.maker = "Toyota"; YourCar.year = 2005; YourCar.price = 30000;

LinkedList inst; inst.insert(MyCar); inst.insert(YourCar);

inst.EscribaUltimo();

return(0);

Running this code as is, I got the compilation error I mentioned earlier.

LoKi
Edit your question with this, not an answer.
GMan