6

我正在尝试编写一个函数来打印常见 STL 容器(向量、列表等)的表示。我给函数一个模板参数 T,例如,它可能代表向量。我在获取 T 类型的迭代器时遇到问题。

vector<int> v(10, 0);
repr< vector<int> >(v);

...

template <typename T>
void repr(const T & v)
{
    cout << "[";
    if (!v.empty())
    {
        cout << ' ';
        T::iterator i;
        for (i = v.begin(); 
             i != v.end()-1;
             ++i)
        {
            cout << *i << ", ";
        }
        cout << *(++i) << ' ';
    }
    cout << "]\n";
}

...

brett@brett-laptop:~/Desktop/stl$ g++ -Wall main.cpp
main.cpp: In function ‘void repr(const T&)’:
main.cpp:13: error: expected ‘;’ before ‘i’
main.cpp:14: error: ‘i’ was not declared in this scope
main.cpp: In function ‘void repr(const T&) [with T = std::vector<int, std::allocator<int> >]’:
main.cpp:33:   instantiated from here
main.cpp:13: error: dependent-name ‘T::iterator’ is parsed as a non-type, but instantiation yields a type
main.cpp:13: note: say ‘typename T::iterator’ if a type is meant

我按照编译器的建议尝试了“typename T::iterator”,但只得到了一个更神秘的错误。

编辑:感谢您的帮助!这是任何想要使用此功能的人的工作版本:

template <typename T>
void repr(const T & v)
{
    cout << "[";
    if (!v.empty())
    {
        cout << ' ';
        typename T::const_iterator i;
        for (i = v.begin(); 
             i != v.end();
             ++i)
        {
            if (i != v.begin())
            {
                cout << ", ";
            }
            cout << *i;
        }
        cout << ' ';
    }
    cout << "]\n";
}
4

3 回答 3

18

您需要typename告诉编译器::iterator应该是一种类型。编译器不知道它是一个类型,因为在实例化模板之前它不知道 T 是什么。例如,它也可以引用一些静态数据成员。这是你的第一个错误。

您的第二个错误是对constv的引用。因此,您必须使用. 您不能向常量容器询问非常量迭代器。::iterator::const_iterator

于 2010-09-17T11:51:46.977 回答
4

更改T::iterator i;typename T::const_iterator i;因为::iteratoris 的类型T并且vconst &.

在合格的依赖类型之前,您需要typename. 如果没有typename,则有一条 C++ 解析规则表示,non-types即使它导致语法错误,也应该解析合格的依赖名称。

typename声明后面的名称应被视为一种类型。否则,名称将被解释为引用非类型。

于 2010-09-17T11:53:04.723 回答
0

也许这会有所帮助:

typename 在引用类型的限定依赖名称之前是必需的,除非该名称正在命名基类或在初始化列表中。在模板中使用限定(但不依赖的名称)之前,类型名是可选的,除非在命名基类或在初始化列表中再次使用。

于 2021-10-23T12:20:35.063 回答