Thread: Output of complex data type

  1. #1
    Registered User
    Join Date
    Feb 2005
    Posts
    38

    Output of complex data type

    Having trouble trying to figure out how to output complex data type to a console. My line of code:

    cout << C.ValueAt(0) << endl;

    gives me error C2679 as follows:
    c:\Documents and Settings\csc9\My Documents\231Ex07HMB\231Ex07DHMB.cpp(64): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'void' (or there is no acceptable conversion)



    Code:
    //.cpp file
    #include "231Ex07LHMB.h"
    #include <conio.h>
    #include <string>
    #include <iostream>
    using namespace std;
    
    	struct Auto{
    		int year;
    		string make;
    		string model;
    	};
    
    	void ShowAuto(ostream& sout, Auto a) {		
    		sout << "\tYear: " << a.year << endl;
    		sout << "\tMake: " << a.make << endl;
    		sout << "\tModel: " << a.model << endl;
    	}
    
    	ostream& operator<<(ostream& sout, Auto a) {
    		ShowAuto(sout, a);
    		return sout;
    	}
    
    int main()
    {
    	//Puts LList Auto data in C
    	LList<Auto> C;
    
    	//Test empty(): Expect "List is empty."
    	cout << "Test empty() before put():\n\t";
    	if(C.empty())
    		cout << "List is empty.\n\n";
    	else
    		cout << "List is not empty.\n\n";
    
    
    	//Datatype Auto, Identifier D
    	Auto D;
    	D.year = 1998;
    	D.make = "Volvo";
    	D.model = "S70";
    
    	//Test for invalid position
    	cout << "Test put() error message for invalid position:\n";
    	C.put(-1, D);
    	C.put(22, D);
    
    
    	//test put()
    	C.put(0, D);
    
    
    	//Test ValueAt()
    	cout << "\nTest ValueAt():\n\t";
    //**ERROR HERE
    	cout << C.ValueAt(0) << endl;
    
    	//Test empty() after put() - Expect: "List is not empty."
    	cout << "\nTest empty() after put():\n\t";
    	if(C.empty())
    		cout << "List is empty.\n\n";
    	else
    		cout << "List is not empty.\n\n";
    
    	//Test for erase()
    	cout << "Test erase():\n";
    	while(!C.empty())
    	{
    		C.erase(0);
    	}
    }
    
    //.h file
    #include <iostream>
    using namespace std;
    
    #define NULL 0
    #define SIZE 256
    
    template <typename T>
    class LList {
    	struct Node {
    		T Data;
    		Node *next;
    	};
    
    public:
    	//Constructor
    	LList();
    
    	//Destructor
    	~LList();
    
    	//empty()
    	bool empty() const;
    
    	//put()
    	void put(int pos, T item);
    
    	//ValueAt()
    	void ValueAt(const long pos);
    
    	//erase()
    	void erase(int pos);
    
    	//display() operation
    	void display(ostream & out) const;
    
    
    private:
    	int mySize;
    	T myList[SIZE];
    	Node  * first;
    };
    
    //Definition of Display
    template<typename T>
    void LList<T>::display(ostream & out) const
    	{
    	for(int i = 0; i < mySize; i++)
    		out << myList[i] << "  ";
    	}
    
    //Constructor
    template<typename T>
    LList<T>::LList()
    {
    	first = NULL;
    	mySize = 0;
    }
    
    //Define Deconstructor
    template<typename T>
    LList<T>::~LList()
    {}
    
    //Define empty()
    template<typename T>
    bool LList<T>::empty() const
    {
    	return(mySize == 0);
    }
    
    //Define put()
    template<typename T>
    void LList<T>::put(int pos, T item)
    	{
    		if(mySize == SIZE)
    
    		{
    		cerr << "\t*** No space for list element -- terminating "
    		"execution ***\n";
    		exit(1);
    		}
    		if (pos < 0 || pos > mySize)
    		{
    		cerr << "\t*** Illegal location to insert -- " << pos
    		<< ".  List unchanged. ***\n";
    			return;
    		}
    
    	//First shift array to the right to make room for item
    		for(int i = mySize; i > pos; i--)
    			myList[i] = myList[i - 1];
    
    	//Now insert item at position pos and increase list size
    	myList[pos] = item;
    	mySize++;
    	}
    
    	//Define ValueAt
    	template<typename T>
    	void LList<T>::ValueAt(const long pos)
    	{	
    		if(mySize == 0)
    		{
    		cerr << "\t*** List is empty ***\n";
    		return;
    		}
    		if(pos < 0 || pos > mySize)
    		{
    		cerr << "\t*** Illegal location to retrieve    value *** " << pos << ".\n";
    		return;
    		}
    		return myList[0];
    	}
    
    //Define erase()
    template<typename T>
    void LList<T>::erase(int pos)
    	{
    		if(mySize == 0)
    		{
    		cerr << "\t*** List is empty ***\n";
    		return;
    		}
    		if(pos < 0 || pos > mySize)
    		{
    		cerr << "Illegal location to delete -- " << pos
    		<< ".  List unchanged ***\n";
    		return;
    		}
    
    	//Shift array elements left to close the gap
    		for(int i = pos; i < mySize; i++)
    			myList[i] = myList[i + 1];
    
    	//Decrease list size
    		mySize--;
    	}

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    c:\Documents and Settings\csc9\My Documents\231Ex07HMB\231Ex07DHMB.cpp(64): error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'void' (or there is no acceptable conversion)
    The error pretty much means what it means:
    Code:
    LList<Auto> C;
    
    ...
    
    cout << C.ValueAt(0) << endl;
    
    ...
    
    //Define ValueAt
    template<typename T>
    void LList<T>::ValueAt(const long pos)
    {
        if(mySize == 0)
        {
            cerr << "\t*** List is empty ***\n";
            return;
        }
        if(pos < 0 || pos > mySize)
        {
            cerr << "\t*** Illegal location to retrieve    value *** " << pos << ".\n";
            return;
        }
    
        return myList[0];
    }
    The ValueAt member function does not currently return a value as given by its definition/declaration so it makes no sense to make it a part of an output statement which expects a value in order to output something. However, the last return statement does attempt to return something, the wrong something apparently (do you mean return myList[pos];?).

    Decide whether you want your function to return a value or not. If it is suppossed to return something, you then need to figure out how to handle your error conditions (where pos < 0 or >= mySize).
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Feb 2005
    Posts
    38
    Thanks hk_mp5kpdw -

    Now I have to make a class QueueL that works with class LList.
    So much to learn.

    Changed to:

    Code:
    cout << C.ValueAt(0) << endl;
    
    //Define ValueAt
    template<typename T>
    T LList<T>::ValueAt(const int pos)
    {	
    	if(mySize == 0)
    	{
    		cerr << "\t*** List is empty ***\n";
    	}
    	if(pos < 0 || pos > mySize)
    	{
    	cerr << "\t*** Illegal location to retrieve value *** " << pos << ".\n";
    	}
    	return myList[pos];
    	}

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> if(pos < 0 || pos > mySize)
    It should also be an error if pos == mySize.

    In that case, you could remove the empty list check (although you would want to leave it in there if you like the more detailed error message).

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    That still doesn't quite work. What if pos is -5? Yes you spit out an error message but you still would try to return myList[-5] which is clearly not what you want. How do you handle a case where the function must return a value but you can still potentially be dealing with an invalid index? What do you return in those cases? Some redesign is in order about how you check for valid indexes and how you print your Auto objects.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    It works as well as an array or std::vector::operator[] does in the same case. It doesn't have to be a requirement to provide defined behavior in cases where invalid positions are passed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why am I getting 'undelcared identifier' ???
    By Bill83 in forum C++ Programming
    Replies: 2
    Last Post: 02-15-2006, 01:00 PM
  2. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Erros in Utility Header File
    By silk.odyssey in forum C++ Programming
    Replies: 4
    Last Post: 12-22-2003, 06:17 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM