为什么在使用 Visual C++ 2022 编译时会出现奇怪的类方法重定义错误?

问题描述 投票:0回答:1

我正在尝试编写我的向量,使其尽可能类似于 STL 版本,我使用了这些类型名称。

        using value_type = Type;

        using iterator = vector_iterator<value_type>;
        using const_iterator = const vector_iterator<value_type>;
        using reverse_iterator = std::reverse_iterator<iterator>;
        using const_reverse_iterator = std::reverse_iterator<const_iterator>;

并实现了很多方法,包括以下迭代器相关的方法。

        constexpr iterator begin() noexcept;
        constexpr const_iterator begin() const noexcept;
        constexpr const_iterator cbegin() const noexcept;

        constexpr iterator end() noexcept;
        constexpr const_iterator end() const noexcept;
        constexpr const_iterator cend() const noexcept;

        constexpr reverse_iterator rbegin() noexcept;
        constexpr const_reverse_iterator rbegin() const noexcept;
        constexpr const_reverse_iterator crbegin() const noexcept;

        constexpr reverse_iterator rend() noexcept;
        constexpr const_reverse_iterator rend() const noexcept;
        constexpr const_reverse_iterator crend() const noexcept;

就像STL中的标准向量一样,每个

begin()
end()
rbegin()
rend()
都有两个重载,返回一个非常量迭代器和一个常量迭代器。
cbegin()
cend()
crbegin()
crend()
被视为返回 const 迭代器的方法的别名。

每组实现看起来像这样(例如

begin()
rend()
):

    // non-const version of begin()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::iterator vector<Type, Allocator>::begin() noexcept
    {
        return iterator(ptr_data_);
    }

    // const version of begin()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::const_iterator vector<Type, Allocator>::begin() const noexcept
    {
        return const_iterator(ptr_data_);
    }

    // cbegin()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::const_iterator vector<Type, Allocator>::cbegin() const noexcept
    {
        return const_iterator(ptr_data_);
    }

    // non-const version of rend()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::reverse_iterator vector<Type, Allocator>::rend() noexcept
    {
        return reverse_iterator(begin());
    }

    // const version of rend()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::const_reverse_iterator vector<Type, Allocator>::rend() const noexcept
    {
        return const_reverse_iterator(begin());
    }

    // crend()
    template <typename Type, typename Allocator>
    constexpr typename vector<Type, Allocator>::const_reverse_iterator vector<Type, Allocator>::crend() const noexcept
    {
        return const_reverse_iterator(cbegin());
    }

然后,当我尝试运行测试项目时,Visual Studio告诉我,

const
版本的
begin()
const
版本的
end()
cbegin()
cend()
由于重新定义而触发
C2373
错误.

C2373 'clb_container::vector::begin': 重新定义;不同类型修饰符

C2373 'clb_container::vector::cbegin': 重新定义;不同类型修饰符

C2373 'clb_container::vector::end': 重新定义;不同类型修饰符

C2373 'clb_container::vector::cend': 重新定义;不同类型修饰符

这是我的

vector_iterator
的构造函数:

    template <typename Type>
    vector_iterator<Type>::vector_iterator(pointer ptr)
    {
        iterator_ptr_ = ptr;
    }

    template <typename T>
    vector_iterator<T>::vector_iterator(const vector_iterator& target)
    {
        iterator_ptr_ = target.iterator_ptr_;
    }

我确信我没有两次定义这些方法。

我已尝试以下步骤:

  • 我把上面提到的方法都注释掉了,重新编译了。错误立即消失。
  • 然后我一一取消注释,发现只要
    const
    版本的
    begin()
    const
    版本的
    end
    cbegin()
    cend()
    之一可用,
    C2373
    就会再次出现。
  • 我将这些代码片段分别传递给 Copilot 和 Claude-3-Sonnet,他们没有发现明显的重新定义。
  • 最后,我用Visual Studio Installer安装了“C++ Clang tools for Windows under Desktopdevelopment with C++”,并配置了测试项目使用Clang。
    C2373
    消失,程序编译正常。但是,如果我将“平台工具集”更改回默认的“Visual Studio 2022(v143)”,则会再次出现错误。所以我认为这个问题很可能是由 Visual C++ 2022 引起的。

但是,作为我小小的STL的一部分,我希望它能够在大多数编译器下正常编译,而不是因为一些莫名其妙的原因而失败,尤其是在像Visual Studio这样用户众多的平台上,但我仍然找不到真正的问题.

c++ visual-c++ iterator visual-studio-2022 redefinition
1个回答
0
投票

constexpr
意味着
const
...

 constexpr iterator begin() noexcept;
 constexpr const_iterator begin() const noexcept;

是相同的东西,除了返回类型。并且您不能执行仅返回类型不同的重载。

© www.soinside.com 2019 - 2024. All rights reserved.