函数返回基类而不是派生类,这是编码错误还是Visual c++ bug ?

Function returns base class instead of derived class, is this a coding mistake or a Visual C++ bug?

本文关键字:编码 错误 Visual bug c++ 基类 返回 派生 函数      更新时间:2023-10-16

给出以下代码,GCC处理得很好。然而,Visual c++ 2010-2015给出了以下错误信息,表明它将reverse_iterator的迭代器成员视为它的基类型,而不是它的派生类型:

"错误1错误C2039: 'get':不是'std::iterator<std::random_access_iterator_tag,element_type,ptrdiff_t,element_type>'的成员"

显然,代码是一个简化的示例,以说明这种情况,并且与原始上下文无关,我们将不在这里处理。唯一需要回答的问题是标题中的问题。

#include <iostream>
#include <iterator>

template <class element_type> class container
{
public:
    class iterator : public std::iterator<std::random_access_iterator_tag, element_type, std::ptrdiff_t, element_type *, element_type &>
    {
    private:
        element_type *a;
    public:
        element_type * get()
        {
            return a;
        }
        void set(element_type *value)
        {
            a = value;
        }
    };

    class reverse_iterator : public std::reverse_iterator<iterator>
    {
    private:
        iterator der1;
    public:
        iterator base()
        {
            return iterator(der1);
        }
    };
};


int main()
{
    using namespace std;
    container<int>::iterator c;
    container<int>::reverse_iterator d;
    cout << c.get() << " ";
    cout << d.base().get() << endl;
    return 0;
}

显然,如果你编译这个,你会发现"c.get()"函数是完美的,d.base().get()提供了错误消息。

这是一个专门用来说明这个问题的构造示例。请不要提供与问题无关的答案。

请注意,当使用另一个人工构造的基类时不会产生此错误-它特定于visual studio下的std::iterator。

注:感谢120programalarm对问题的回答。解决方案是在reverse_iterator中澄清迭代器实例的名称空间,以便使用container::iterator。要做到这一点,只需在reverse_iterator声明中使用"typename container::iterator"而不是"iterator"。

reverse_iterator来源于std::iterator(它在<xutility>中),因此您在reverse_iterator类中对iterator的引用将参考std版本,而不是您的类。

不继承std::reverse_iterator

#include <iterator>

template <class element_type> class container
{
public:
    class iterator : public std::iterator<std::random_access_iterator_tag, element_type, std::ptrdiff_t, element_type *, element_type &>
    {
    private:
        element_type *a;
    public:
        element_type get()
        {
            return *a;
        }
        void set(element_type *value)
        {
            *a = value;
        }
    };
    using reverse_iterator = std::reverse_iterator<iterator>;
    iterator begin();
    reverse_iterator rbegin() {
         return std::make_reverse_iterator( end() );
    }
};