4

I have a template class which contains a vector of pointers of a type given as a template parameter. I want to be able to use range-based iteration to iterate over a limited portion of the vector. My class contains the following functions:

template< typename ObjectType >
class ObjectList
{

    ...

public:

    //! Begin iteration over a list of objects
    std::vector<ObjectType*>::iterator begin();

    //! Iterator to one past the end of the list of objects
    std::vector<ObjectType*>::iterator end();

private:

    std::vector<ObjectType*> object_ptrs;
};

This fails to compile with the description Error C2061 syntax error: identifier 'iterator'. I can't think of any reason why std::vector<ObjectType>::iterator should ever not be found, unless ObjectType itself cannot be found, but the rest of the class instantiates successfully if I remove the lines which reference iterator.

Anyone have an idea what is going on? I'm sure it's possible I'm missing something obvious. Thanks in advance!

5
  • Could you tell us the compiler you use ? Because mine (gcc 5.3) is pretty explicit about this problem.
    – kebs
    Commented Jan 22, 2016 at 8:00
  • About iterating over a limited portion of a container, it's not currently supported by the standard library. There may be ranges coming to the next (C++17 supposedly) standard. There are libraries you can use though. Commented Jan 22, 2016 at 8:02
  • @kebs I'm using msvc, unfortunately. I suppose I should make a habit of trying things in both when I don't understand the error.
    – stett
    Commented Jan 22, 2016 at 8:24
  • @Joachim Pileborg I disagree with the duplicate tag, the question here is "why doesn't this compile ?" which is not the same question as the other.
    – kebs
    Commented Jan 22, 2016 at 8:36
  • @JoachimPileborg The fact that ranges are not supported in the way that I need is precisely the reason that I am building this class. It seems too small of a reason to bother including another library just for this, and besides, it's always good for me to learn new stuff :D
    – stett
    Commented Jan 22, 2016 at 8:39

3 Answers 3

1

You should use typename here, because std::vector<ObjectType*> is a dependent type name which depends on the template parameter ObjectType.

typename std::vector<ObjectType*>::iterator begin();
typename std::vector<ObjectType*>::iterator end();

$14.6/2 Name resolution [temp.res]

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

1

You need to tell the compiler that iterator is a type, as it depends on a template parameter:

template< typename ObjectType >
class ObjectList
{
public:

    //! Begin iteration over a list of objects
    typename std::vector<ObjectType*>::iterator begin();

    //! Iterator to one past the end of the list of objects
    typename std::vector<ObjectType*>::iterator end();

private:

    std::vector<ObjectType*> object_ptrs;
};
1

Compiler does not know, whenever iterator is a type or a static member. You have to add typename before the function return type in order to help compiler to disambiguate:

typename std::vector<ObjectType*>::iterator begin();

Also, new g++ (at least, since 5.3.0) produces more readable error message:

main.cpp:11:5: error: need typename before std::vector<ObjectType*>::iterator because std::vector<ObjectType*> is a dependent scope std::vector<ObjectType*>::iterator begin()

Not the answer you're looking for? Browse other questions tagged or ask your own question.