tags:

views:

100

answers:

4

Hello all :)

I need to get a reference to an iterator of a reference. However, my compiler is choking on this code:

template <typename InputIterator> size_t iLongestBegin(InputIterator first, InputIterator last)
{
    typedef typename std::iterator_traits<InputIterator>::reference SequenceT;
        //Problem is next line
    typedef typename std::iterator_traits<typename SequenceT::iterator>::reference T;
    for(size_t idx; idx < first->length(); idx++)
    {
     T curChar = (*first)[idx];
     for (InputIterator cur = first; cur != last; cur++)
     {
      if (cur->length() < idx)
       return idx;
      if (_tolower(cur->at(idx)) != _tolower(curChar))
       return idx;
     }
    }
    return first->length();
}

Any ideas on how to fix it? The error is

error C2825: 'SequenceT': must be a class or namespace when followed by '::'

Thanks! Billy3

A: 

Did you miss specifying SequenceT in the template argument list - Where is it defined? Or maybe you must indicate that it's a type with typename SequenceT.

Dario
It's a typedef on the line prior to the one he flagged as an error.
anon
The function is passed a std::list<std::basic_string<wchar_t> > .
Billy ONeal
+1  A: 

You need to write typename SequenceT::iterator instead of just SequenceT::iterator. This is because SequenceT is a type that is derived from your template parameters (a "dependent type", in standard lingo), and iterator is a nested type in SequenceT, not a function or variable. When both of these things are true, the compiler can't figure out what you mean and needs to be told that SequenceT::iterator is a type with typename.

Doug
Changed it to "typedef typename std::iterator_traits<typename SequenceT::iterator>::reference T;" Still no joy
Billy ONeal
Doug
T should be wchar_t given that the iterators are pointing to a std::list<std::basic_string<wchar_t> >
Billy ONeal
A: 

The following compiles with g++ 4.4.0:

#include <iterator>
using namespace std;

template <typename InputIterator> size_t iLongestBegin(InputIterator first, InputIterator last) {
   typedef typename std::iterator_traits<InputIterator>::reference SequenceT;
   typedef typename std::iterator_traits<typename SequenceT::iterator>::reference T;
   for(size_t idx; idx < first->length(); idx++)
   {
      T curChar = (*first)[idx];
      for (InputIterator cur = first; cur != last; cur++)
      {
         if (cur->length() < idx)
             return idx;
         if (_tolower(cur->at(idx)) != _tolower(curChar))
             return idx;
      }
   }
    return first->length();
}
anon
Mine compiles fine too until I call it. Did you throw test data at it?
Billy ONeal
No. If you have problems with code that is only demonstrable with certain test data, please include the test code in your question.
anon
The problem code is there. My compiler doesn't even attempt to resolve the types and compile any template functions unless they are called. Not sure if GCC behaves that way.
Billy ONeal
A C++ compiler must process the template, whether it is used or not.
anon
+1  A: 

Actually, just solved it :)

Problem is that SequenceT is a reference, not a type. Since you can't generally take the address of a reference type, the compiler won't generate iterators for it. I need to use value_type instead of reference:

template <typename InputIterator> size_t iLongestBegin(InputIterator first, InputIterator last)
{
    typedef typename std::iterator_traits<InputIterator>::reference SequenceT;
    typedef typename std::iterator_traits<std::iterator_traits<InputIterator>::value_type::iterator>::reference T;
    for(size_t idx; idx < first->length(); idx++)
    {
     typename T curChar = (*first)[idx];
     for (InputIterator cur = first; cur != last; cur++)
     {
      if (cur->length() < idx)
       return idx;
      if (_tolower(cur->at(idx)) != _tolower(curChar))
       return idx;
     }
    }
    return first->length();
}
Billy ONeal
You still have some things wrong. "typename T" should be just "T", and there is "typename" needed before "std::iterator_traits<InputIterator>::value_type::iterator" . Looks like you compile with some too lax compiler. Later if you want to compile with another one, you will get many problems
Johannes Schaub - litb
Doesn't really bother me for now. Only compiler this thing will ever be pointed at is msvc++. Thank you though :)
Billy ONeal