c++googletestconst-iterator

Why my custom const_iterator end() function does not compile while using gtest?


I'm trying to learn how the c++ standard library works and it's data structures and I'm implementing an array and some iterators just for learning purposes. I'm using Gtest/gmock to do some TDD with VisualStudio 2022 and I'm currently have the array, const_iterator and iterator classes with their corresponding tests and everything is working fine.

But when I add the code for the iterator functions (begin, end, cbegin, cend) in the array struct, gtest fails to compile throwing me an error that corresponds to the const_iterator end() const function.

Build started at 6:45 PM...
1>------ Build started: Project: CppStd Test, Configuration: Debug x64 ------
1>array_test.cpp
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25): error C2440: '<function-style-cast>': cannot convert from 'const int *' to 'cppstd::const_iterator<T>'
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25): error C2440:         with
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25): error C2440:         [
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25): error C2440:             T=int
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25): error C2440:         ]
1>(compiling source file 'array_test.cpp')
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>'cppstd::const_iterator<T>::const_iterator': no overloaded function could convert all the argument types
1>        with
1>        [
1>            T=int
1>        ]
1>  C:\Users\PC\Visual Studio\CppStd\CppSTD\const_iterator.h(130,1):
1>  could be 'cppstd::const_iterator<T>::const_iterator(cppstd::const_iterator<T> &&)'
1>        with
1>        [
1>            T=int
1>        ]
1>      C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>      'cppstd::const_iterator<T>::const_iterator(cppstd::const_iterator<T> &&)': cannot convert argument 1 from 'const int *' to 'cppstd::const_iterator<T> &&'
1>        with
1>        [
1>            T=int
1>        ]
1>          C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,38):
1>          Reason: cannot convert from 'const int *' to 'cppstd::const_iterator<T>'
1>        with
1>        [
1>            T=int
1>        ]
1>  C:\Users\PC\Visual Studio\CppStd\CppSTD\const_iterator.h(130,1):
1>  or       'cppstd::const_iterator<T>::const_iterator(const cppstd::const_iterator<T> &)'
1>        with
1>        [
1>            T=int
1>        ]
1>      C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>      'cppstd::const_iterator<T>::const_iterator(const cppstd::const_iterator<T> &)': cannot convert argument 1 from 'const int *' to 'const cppstd::const_iterator<T> &'
1>        with
1>        [
1>            T=int
1>        ]
1>          C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,38):
1>          Reason: cannot convert from 'const int *' to 'const cppstd::const_iterator<T>'
1>        with
1>        [
1>            T=int
1>        ]
1>  C:\Users\PC\Visual Studio\CppStd\CppSTD\const_iterator.h(31,3):
1>  or       'cppstd::const_iterator<T>::const_iterator(int *) noexcept'
1>        with
1>        [
1>            T=int
1>        ]
1>      C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>      'cppstd::const_iterator<T>::const_iterator(int *) noexcept': cannot convert argument 1 from 'const int *' to 'int *'
1>        with
1>        [
1>            T=int
1>        ]
1>          C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,38):
1>          Conversion loses qualifiers
1>  C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>  while trying to match the argument list '(const int *)'
1>C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(55,25):
1>the template instantiation context (the oldest one first) is
1>  C:\Users\PC\Visual Studio\CppStd\CppStd Test\array_test.cpp(64,30):
1>  see reference to class template instantiation 'cppstd::array<int,3>' being compiled
1>  C:\Users\PC\Visual Studio\CppStd\CppSTD\array.h(53,42):
1>  while compiling class template member function 'cppstd::const_iterator<T> cppstd::array<T,3>::end(void) noexcept const'
1>        with
1>        [
1>            T=int
1>        ]
1>      C:\Users\PC\Visual Studio\CppStd\packages\gmock.1.11.0\lib\native\include\gtest\gtest-printers.h(136,24):
1>      see the first reference to 'cppstd::array<int,3>::end' in 'testing::internal::ContainerPrinter::PrintValue'
1>const_iterator_test.cpp
1>iterator_test.cpp
1>Generating Code...
1>Done building project "CppStd Test.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 6:45 PM and took 11.959 seconds ==========

My implementation of the failure compile is the following:

template<typename T, std::size_t Size>
struct array
{
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = value_type&;
    using const_reference = const value_type&;
    using pointer = value_type*;
    using const_pointer = const value_type*;
    using iterator = cppstd::iterator<T>;
    using const_iterator = cppstd::const_iterator<T>;
    
    value_type m_array[Size];

    [[nodiscard]] constexpr iterator begin() noexcept
    {
        return iterator(&m_array[0]);
    }

    [[nodiscard]] constexpr iterator end() noexcept
    {
        return iterator(&m_array[0] + Size);
    }

    [[nodiscard]] constexpr const_iterator begin() const noexcept
    {
        return const_iterator(&m_array[0]);
    }

    [[nodiscard]] constexpr const_iterator end() const noexcept
    {
        // HERE IS WHERE I GET THE ERROR
        return const_iterator(&m_array[0] + Size);
    }
};


template<typename T>
class const_iterator
{
public:
    using iterator_category = std::random_access_iterator_tag;
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = value_type&;
    using pointer = value_type*;
    using const_reference = const value_type&;
    using const_pointer = const value_type*;

    T* m_pointer;

    const_iterator() = default;

    explicit const_iterator(pointer ptr) noexcept : m_pointer{ ptr } {}
};

The error stops if I change the name of the function for anything else and it keeps appearing even if I don't have any test or types referring to my iterator or array class.

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include "../CppSTD/const_iterator.h"

using namespace ::testing;

class const_iterator_test : public Test
{
public:
    void SetUp() override
    {
        ptr_int = new int[5];
        for (int i{ 0 }; i < 5; ++i)
            ptr_int[i] = i + 1;
    }

    void TearDown() override
    {
        delete ptr_int;
        ptr_int = nullptr;
    }

    int* ptr_int{ nullptr };

private:

};

Perhaps is something very obvious that I don't see. And is very weird because if I compile without gtest everything runs normally. I leave here the full definition of my array and iterator classes: FULL CODE

Thank you in advance.


Solution

  • 'cppstd::const_iterator<T>::const_iterator(int *) noexcept': cannot convert argument 1 from 'const int *' to 'int *'
    

    In the class const_iterator, the constructor

    explicit const_iterator(pointer ptr) noexcept : m_pointer{ ptr } {}
    

    should be

    explicit const_iterator(const_pointer ptr) noexcept : m_pointer{ ptr } {}
    

    And

    T* m_pointer;
    

    should be

    const_pointer m_pointer;
    // const T* m_pointer;