-1

I wrote a class and I wanted to implement an iterator for it ( as shown in the following code ). I needed to overload a variety of operators and I faced the error mentioned below:

class BaseClass
{
    virtual ~BaseClass() {}
};

template<class T>
class AbstractBaseOrgan: public BaseClass
{
public:
    typedef T value;
    template<class TT>
    class AbstractBaseIterator:
        public std::iterator<std::random_access_iterator_tag,
        typename std::iterator_traits<TT>::value_type>
    {
    protected:
        TT _M_current;
        const TT&
        base() const
        { return this->_M_current; }
    };
protected:
    value te;
};


template<typename Iter>
inline bool
operator<(const typename AbstractBaseOrgan<typename 
    std::iterator_traits<Iter>::value_type>::template 
    AbstractBaseIterator<Iter>& lhs,
    const typename AbstractBaseOrgan<typename 
    std::iterator_traits<Iter>::value_type>::template 
    AbstractBaseIterator<Iter>& rhs)
{ return lhs.base() < rhs.base(); }

int main()
{
    AbstractBaseOrgan<int>::AbstractBaseIterator<int*> temp;
    AbstractBaseOrgan<int>::AbstractBaseIterator<int*> temp2;
    int ttemp;
    if(operator< (temp,temp2))
        ttemp = 0;
    return 0;
} 

Compiling it gives me the following error:

error: no matching function for call to ‘operator<(AbstractBaseOrgan<int>::AbstractBaseIterator<int*>&, AbstractBaseOrgan<int>::AbstractBaseIterator<int*>&)’

Any idea what might cause this?

Bart
  • 19,692
  • 7
  • 68
  • 77
sorosh_sabz
  • 2,356
  • 2
  • 32
  • 53

1 Answers1

1

4 In most cases, the types, templates, and non-type values that are used to compose P participate in template argument deduction. That is, they may be used to determine the value of a template argument, and the value so determined must be consistent with the values determined elsewhere. In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

The non-deduced contexts are: — The nested-name-specifier of a type that was specified using a qualified-id.

You can avoid this by few ways. First way - make operator < friend for class AbstractIteratorBase, or its member.

template<class TT>
class AbstractBaseIterator:
    public std::iterator<std::random_access_iterator_tag,
    typename std::iterator_traits<TT>::value_type>
{
    public:
        template<typename Iter>
        friend bool operator < (const AbstractBaseIterator<Iter>& lhs, const AbstractBaseIterator<Iter>& rhs)
        {
            return lhs.base() < rhs.base();
        }
protected:
    TT _M_current;
    const TT&
    base() const
    { return this->_M_current; }
};

Second variant is define AbstractBaseIterator class not in template class. And then typedef AbstractBaseIterator<T> iterator; in AbstractBaseOrgan. If you can use C++11 you can use something like this.

class BaseClass
{
    virtual ~BaseClass() {}
};

template<class TT>
class AbstractBaseIterator:
public std::iterator<std::random_access_iterator_tag,
typename std::iterator_traits<TT>::value_type>
{
protected:
    TT _M_current;
    const TT&
    base() const
    { return this->_M_current; }
};

template<typename Iter>
bool operator < (const AbstractBaseIterator<Iter>& lhs, const AbstractBaseIterator<Iter>& rhs)
{
   return lhs.base() < rhs.base();
}

template<class T>
class AbstractBaseOrgan: public BaseClass
{
public:
    typedef T value;
    template<typename TT>
    using iterator = AbstractBaseIterator<TT>;
protected:
    value te;
};

int main()
{
    AbstractBaseOrgan<int>::iterator<int*> temp;
    AbstractBaseOrgan<int>::iterator<int*> temp2;
    int ttemp;
    if(operator< (temp,temp2))
        ttemp = 0;
    return 0;
}
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • One of the more ugly scenarios one can run into. – pmr Jul 30 '12 at 16:00
  • @user1539100 i rewrite my answer. first comment about another answer. – ForEveR Jul 30 '12 at 17:17
  • @ForEveR thank you for your answer. whith your solution my problem has solved but i found new problem. :94: error: redefinition of ‘template bool operator<(const AbstractBaseOrgan::AbstractBaseIterator&, const AbstractBaseOrgan::AbstractBaseIterator&)’ :94: error: ‘template bool operator<(const AbstractBaseOrgan::AbstractBaseIterator&, const AbstractBaseOrgan::AbstractBaseIterator&)’ previously defined here – sorosh_sabz Jul 31 '12 at 11:45
  • @user1539100 which solution you trying to use? Give code please. http://liveworkspace.org/ write here, click run and give link please. – ForEveR Jul 31 '12 at 15:19
  • @ForEveR : thank you for your response the link is : http://liveworkspace.org/code/5d166208abe3869f61087bbaecad2250 – sorosh_sabz Jul 31 '12 at 16:55
  • @user1539100 Okay, it's really problem http://liveworkspace.org/code/3e6c1cad1bffc9ea3b1133dce5cabf97. I think the most good solution is to not use nested template classes, or rewrite your code at all. But why not use simply http://liveworkspace.org/code/6801df09140dfb8923c0e0262ce94d29 ? – ForEveR Jul 31 '12 at 20:56
  • @ForEveR : thank you for your response, the reason i am using nested template classes is that the outer class just has the permision to control the inner class and so no other classes can get an instance from the inner class without the permision of the outer class, in other words i want to have two classes that one is controled by the other. do you have any ideas different from what I did to implement this concept? – sorosh_sabz Aug 01 '12 at 00:26