如何在模板化类中使用 std::map 迭代器?

发布于 2024-12-18 15:29:54 字数 1005 浏览 2 评论 0原文

我在类模板中使用私有 std::map 变量时遇到问题。谁能解释为什么以下(简化的示例)不起作用,以及我应该做什么?

#include <iostream>
#include <map>

template <class T>
class Container
{
    private:
        typedef std::map<long, T> Map;
        typedef Map::iterator Iterator; // <-- this is line 10
        Map items;
    public:
        void insert(const long id, const T& item) { items[id] = item; }
        void print()
        {
            for (Iterator iter = items.begin(); iter != items.end(); iter++)
            { std::cout << iter->second << std::endl; }
        }
};

int main()
{
    Container<int> container;

    container.insert(300, 1);
    container.insert(200, 2);
    container.insert(100, 3);

    container.print();

    return 0;
}

由此产生的错误有点神秘:

t.cpp:10: 错误:类型 'std::map, std::allocator > >'不是从类型“Container”派生的

t.cpp:10: 错误:ISO C++ 禁止声明没有类型的“迭代器”

t.cpp:10: 错误:预期为“;”在“迭代器”之前

I am having trouble using a private std::map variable from within a class template. Can anyone explain why the following (simplified example) does not work, and what I should be doing instead?

#include <iostream>
#include <map>

template <class T>
class Container
{
    private:
        typedef std::map<long, T> Map;
        typedef Map::iterator Iterator; // <-- this is line 10
        Map items;
    public:
        void insert(const long id, const T& item) { items[id] = item; }
        void print()
        {
            for (Iterator iter = items.begin(); iter != items.end(); iter++)
            { std::cout << iter->second << std::endl; }
        }
};

int main()
{
    Container<int> container;

    container.insert(300, 1);
    container.insert(200, 2);
    container.insert(100, 3);

    container.print();

    return 0;
}

The resulting error is somewhat cryptic:

t.cpp:10: error: type 'std::map, std::allocator > >' is not derived from type 'Container'

t.cpp:10: error: ISO C++ forbids declaration of 'iterator' with no type

t.cpp:10: error: expected ';' before "Iterator"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无名指的心愿 2024-12-25 15:29:54

您需要限定依赖类型名称:

    typedef typename Map::iterator Iterator;

基本原理:编译器在解析模板时,无法确定是类型还是表达式。这是因为名称取决于模板参数,而模板参数仅在实例化时才知道。

你必须帮助编译器。


旁注:

  • MSVC 似乎对此规则不严格,因为它的模板实例化引擎以非标准方式运行,并且无论如何,直到实例化时间才会完成名称查找

  • 有时,依赖成员模板也需要进行限定:

    模板 结构ContrivedSample
    {
        a元组数据;
    
        无效 foo()
        {
           auto v = data.template get<0>(); // 需要模板
        }
    };
    

You need to qualify the dependant typename:

    typedef typename Map::iterator Iterator;

Rationale: the compiler, at the time of parsing the template, cannot work out whether is a type or a value expression. This is because the names depend on the template argument(s), which are only known at instantiation time.

You have to help the compiler out.


Sidenotes:

  • MSVC seems to be lax with this rule, as it's template instantiation engine behaves in non-standard ways, and the name lookups aren't done until instantiation time anyway

  • sometime, dependent member templates need to be qualified as well:

    template <typename aTuple> struct ContrivedSample
    {
        aTuple data;
    
        void foo()
        {
           auto v = data.template get<0>(); // template required
        }
    };
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文