9 Replies - 1224 Views - Last Post: 12 February 2010 - 02:18 AM Rate Topic: -----

#1 Guest_Sethcran*


Reputation:

Returning a nested object

Posted 12 February 2010 - 12:52 AM

So, I'm doing a project currently, and getting stumped by something minor, and I'm sure that I'm just totally missing something stupid, but it's a little part that has little to do with most of the rest of the project.

We're basically just making an implementation file for a double linked list. We were given a header file with all of the functions to implement, and all we have to do is write the implementation file. Most of it is very easy, and I'm fairly sure that I have a good understanding of the concept itself, as well as how to write most of the functions.

Where I'm running into a problem however is with the nested class iterator. Basically, the initial declaration is something like this in the header file:

namespace name
{
    template < typename T>
    class List
    {
    public:
        class const_iterator
        {
        public:
            const_iterator();
            const_iterator & operator++();
            ...
         }
    }
}


So when writing the implementation file, I did the constructor like the following:

template <typename T>
name::List<T>::const_iterator::const_iterator() : current( NULL )
{}


And I can do that for all of the functions unless their is a better way ( I wish I could just do all this code inline, and wouldn't have an issue, but we're unable to modify the header file, and can only touch the .cpp implementation file ), but with the second function ( there are others, but these 2 serve the purpose of examples to show my issue ), I'm unsure how to write the first line of the operator++ function, because it returns a nested object, and I get an error similar to the following when I try:

list.cpp(14) : error C2143: syntax error : missing ';' before 'name::List<T>::const_iterator::++'

I've tried versions such as:

const_iterator name::List<T>::const_iterator::operator++()

or

name::List<T>::const_iterator & name::List<T>::const_iterator::operator++()



But to be honest I have no experience with nested classes and am unsure quite how to implement returning an object of a nested class in an implementation file.

Is This A Good Question/Topic? 0

Replies To: Returning a nested object

#2 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Returning a nested object

Posted 12 February 2010 - 12:56 AM

Take a look at how lists are implemented in the c++ library. You should then be able to see how it's done.
Was This Post Helpful? 0
  • +
  • -

#3 Guest_Sethcran*


Reputation:

Re: Returning a nested object

Posted 12 February 2010 - 01:19 AM

Any chance you could point me in the right direction where I might find these please? I've google searched several times, gone through my book and the teachers powerpoints, but every single example I've found is all written inline :(
Was This Post Helpful? 0

#4 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Returning a nested object

Posted 12 February 2010 - 01:23 AM

View PostSethcran, on 12 February 2010 - 07:19 AM, said:

Any chance you could point me in the right direction where I might find these please? I've google searched several times, gone through my book and the teachers powerpoints, but every single example I've found is all written inline :(


Ignore the inline keyword. The code will be the same.
Was This Post Helpful? 0
  • +
  • -

#5 Guest_Sethcran*


Reputation:

Re: Returning a nested object

Posted 12 February 2010 - 01:31 AM

I meant that they are all written in one file, for example:

class highclass
{
    class nestedclass
    {
        nestedclass( int )
        {
          implementation;
        }
    }
}


Where the code is all in one single .h file, rather than split into the header and implementation.

I'm just having trouble understanding how to properly use the scope resolution operator to return an object of a nested class, I think at least, and that's what I can't find, any examples that are seperated into two files using the :: operator and whatnot, if you could point me to a link describing it, or explain it, either way, would <3 forever.
Was This Post Helpful? 0

#6 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Returning a nested object

Posted 12 February 2010 - 01:44 AM

Try not to put too much implementation code into a class definition.

In your example

class highclass 
{ 
    class nestedclass 
    { 
        nestedclass( int ) 
        { 
          implementation; 
        } 
    } 
}



do it this way

class highclass 
{ 
    class nestedclass 
    { 
        nestedclass( int );
    } 
}

highclass::nestedclass::nestedclass( int ) 
{ 
    implementation; 
} 



Hope that is self-explainatory
Was This Post Helpful? 0
  • +
  • -

#7 Guest_Sethcran*


Reputation:

Re: Returning a nested object

Posted 12 February 2010 - 01:50 AM

View PostMartyn.Rae, on 12 February 2010 - 12:44 AM, said:

Try not to put too much implementation code into a class definition.

In your example

class highclass 
{ 
    class nestedclass 
    { 
        nestedclass( int ) 
        { 
          implementation; 
        } 
    } 
}



do it this way

class highclass 
{ 
    class nestedclass 
    { 
        nestedclass( int );
    } 
}

highclass::nestedclass::nestedclass( int ) 
{ 
    implementation; 
} 



Hope that is self-explainatory





Right, and that's what I've done, as I showed with the constructor example in my first post. Where I'm getting an error, is trying to do that when the function I am implementing returns an object to the nested class:

name::List<T>::const_iterator& cop4530::List<T>::const_iterator::operator++()
{
	current = current->next;
	return *this;
}



This gives the following errors:

warning C4346: 'cop4530::List<T>::const_iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type

error C2143: syntax error : missing ';' before '&'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

I've tried a few different ways of setting it up, but I don't think I'm understanding the syntax of the return type. Just setting up the constructor, or a function with any other return type works just fine:

template <typename T>
const T& name::List<T>::const_iterator::operator*() const
{
	return retrieve();
}



For example, this one compiles just fine. It's just the part about returning an object of the nested iterator class that I'm having an issue with :(
Was This Post Helpful? 0

#8 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Returning a nested object

Posted 12 February 2010 - 01:59 AM

Can you post the header file and the implementation file as they stand right now and I will take a look at them.
Was This Post Helpful? 0
  • +
  • -

#9 Guest_Sethcran*


Reputation:

Re: Returning a nested object

Posted 12 February 2010 - 02:03 AM

I've really only just started on it before running into this problem, so I havn't gotten around to writing too much of the actual implementation yet, although i'm confident that it won't take me long once I do get around this, as the code itself really isn't difficult.

The assigned header file is:

#ifndef DL_LIST_H
#define DL_LIST_H
#include <iostream>

namespace name {

template <typename T>
class List {
 private:
    // nested Node class
    struct Node {
	T data;
	Node *prev;
	Node *next;

	Node(const T & d = T(), Node *p = NULL, Node *n = NULL) 
	    : data(d), prev(p), next(n) {}
    };

 public:
    //nested const_iterator class
    class const_iterator {
    public:
	const_iterator(); // default zero parameter constructor
	const T & operator*() const; // operator*() to return element

	// increment/decrement operators
	const_iterator & operator++();
	const_iterator operator++(int);
	const_iterator & operator--();
	const_iterator operator--(int);

	// comparison operators
	bool operator==(const const_iterator &rhs) const;
	bool operator!=(const const_iterator &rhs) const;

    protected:
	Node *current; // pointer to node in List
	T & retrieve() const; // retrieve the element refers to
	const_iterator(Node *p); // protected constructor

	friend class List<T>;
    };

    // nested iterator class
    class iterator : public const_iterator {
    public:
	iterator() {}
	T & operator*();
	const T & operator*() const;
	
	// increment/decrement operators
	iterator & operator++();
	iterator operator++(int);
	iterator & operator--();
	iterator operator--(int);

    protected:
	iterator(Node *p);
	friend class List<T>;
    };

 public:
    // constructor, desctructor, copy constructor
    List(); // default zero parameter constructor
    List(const List &rhs); // copy constructor
    // num elements with value of val
    explicit List(int num, const T& val = T()); 
    // constructs with elements [start, end)
    List(const_iterator start, const_iterator end); 
                      
    ~List(); // destructor

    // assignment operator
    const List& operator=(const List &rhs);
    
    // member functions
    int size() const; // number of elements
    bool empty() const; // check if list is empty
    void clear(); // delete all elements
    void reverse(); // reverse the order of the elements

    T &front(); // reference to the first element
    const T& front() const;
    T &back(); // reference to the last element
    const T & back() const; 
    
    void push_front(const T & val); // insert to the beginning
    void push_back(const T & val); // insert to the end
    void pop_front(); // delete first element
    void pop_back(); // delete last element

    void remove(const T &val); // remove all elements with value = val
    
    // print out all elements. ofc is deliminitor
    void print(std::ostream& os, char ofc = ' ') const; 

    iterator begin(); // iterator to first element
    const_iterator begin() const;
    iterator end(); // end marker iterator
    const_iterator end() const; 
    iterator insert(iterator itr, const T& val); // insert val ahead of itr
    iterator erase(iterator itr); // erase one element
    iterator erase(iterator start, iterator end); // erase [start, end)

    
private:
    int theSize; // number of elements
    Node *head; // head node
    Node *tail; // tail node

    void init(); // initialization
};

// overloading comparison operators
template <typename T>
bool operator==(const List<T> & lhs, const List<T> &rhs);

template <typename T>
bool operator!=(const List<T> & lhs, const List<T> &rhs);

// overloading output operator
template <typename T>
std::ostream & operator<<(std::ostream &os, const List<T> &l);

}

#endif



As far as the implementation goes, I started on the first 2 functions just fine, but the 3rd function is what I have been having the issue with:

#include "List.h"

template <typename T>
cop4530::List<T>::const_iterator::const_iterator() : current( NULL )
{}

template <typename T>
const T& cop4530::List<T>::const_iterator::operator*() const
{
	return retrieve();
}


/* This one is the problem, as I get compiler errors in trying to get the return type correct */
template <typename T>
cop4530::List<T>::const_iterator& cop4530::List<T>::const_iterator::operator++()
{
	current = current->next;
	return *this;
}

Was This Post Helpful? 0

#10 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: Returning a nested object

Posted 12 February 2010 - 02:18 AM

You need to put 'typename' just at the start of the second line. It will then compile for you.

/* This one is the problem, as I get compiler errors in trying to get the return type correct */ 
template <typename T> 
typename List<T>::const_iterator& List<T>::const_iterator::operator++() 
{ 
        current = current->next; 
        return *this; 
}


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1