Search code examples
c++iteratoroperator-overloadingb-tree

C++ Error with the operator* in a custom iterator for a b-tree


I'm getting the following error when trying to return the value using the operator*() in my custom iterator.

 error: invalid initialization of non-const reference of type 'char&' from a temporary of type 'char'

If anyone is able to help me out, that would be great!

The specifics of the code is as follows:

Test code:

  for(btree<char>::iterator itr = tree.begin(); itr != tree.end(); ++itr) {

    cout << *itr << " "; // <- this line complains about the * operator.
  }

The operator*() code:

template <typename T> typename btree_iterator<T>::reference btree_iterator<T>::operator*() const {

  return pointee_->value(); // <- this line is where the error above is produced from.
}

pointee_ from the btree_iterator class is a private variable defined as follows:

btree_node<T>* pointee_;

reference is typefef'ed as the following in the btree_iterator class:

  typedef T&       reference;

value() is defined in the btree_node class as follows:

T value() const;

// function definition.
template <typename T> T btree_node<T>::value() const { return value_; }

value is initially stored into a btree_node via it's constructor as follows:

template <typename T> btree_node<T>::btree_node(const T& elem) : value_(elem), nextCont_(NULL), prevCont_(NULL), nextNode_(NULL), prevNode_(NULL) {}

Please let me know if i missed including any crucial information, and apologies if i did!

Based on the error, it sounds like I'm trying to return a reference to a local variable. The iterator itself may be local, but the value that it is returning shouldn't be, since the node constructor originally takes in a reference, and stores that into the node.

Thanks in advance, and regards!


Solution

  • You're trying to use a reference to a temporary variable

    template <typename T> T btree_node<T>::value() const { return value_; }
                         ^^^
    

    This returns a temporary copy of value_.

    template <typename T> typename btree_iterator<T>::reference btree_iterator<T>::operator*() const {
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      return pointee_->value(); // <- this line is where the error above is produced from.
    }
    

    This returns a reference to that temporary copy. You most likely want value() to return a reference, but this is up to you - a reference allows clients of your btree to alter the contents. Especially if the tree is ordered based upon the value of the node, you may not want to allow this. Have a think how this is relevant to your design.