0

I'm reinventing std::array with minimal functions:

#include <iostream>
#include <cstddef>

template <typename T, size_t N>
class MyArray {
public:
    class Iterator {
    public:
        Iterator(): ptr(nullptr) {}
        T &operator*() { return *ptr; }
        T *operator->() { return ptr; }
        // Iterator + Int
        Iterator operator+(int n) { return Iterator(ptr + n); }

    private:
        Iterator(T *ptr): ptr(ptr) {}
        T *ptr;

        friend class MyArray;
    };

    T &operator[](int n) { return arr[n]; }
    Iterator begin() { return Iterator(arr); }
    Iterator end() { return Iterator(arr + N); }

private:
    T arr[N];
};

// Int + Iterator
template<typename T, size_t N>
typename MyArray<T, N>::Iterator operator+(int n, typename MyArray<T, N>::Iterator it) {
    return it + n;
}

int main(void) {
    MyArray<long, 10> arr;
    arr[0] = 0;
    arr[1] = 1;

    auto it = arr.begin();
    std::cout << *it << std::endl;          // prints 0
    std::cout << *(it + 1) << std::endl;    // prints 1
    std::cout << *(1 + it) << std::endl;    // compile error!
}

As shown above, it supports indexing and a forward iterator. However, operator overloading for int + iterator raises a compile error. GCC 12.1.0 says:

test.cpp: In function ‘int main()’:
test.cpp:44:22: error: no match for ‘operator+’ (operand types are ‘int’ and ‘MyArray<long int, 10>::Iterator’)
   44 |     std::cout << *(1 + it) << std::endl;    // compile error!
      |                    ~ ^ ~~
      |                    |   |
      |                    int MyArray<long int, 10>::Iterator
test.cpp:32:34: note: candidate: ‘template<class T, long unsigned int N> typename MyArray<T, N>::Iterator operator+(int, typename MyArray<T, N>::Iterator)’
   32 | typename MyArray<T, N>::Iterator operator+(int n, typename MyArray<T, N>::Iterator it) {
      |                                  ^~~~~~~~
test.cpp:32:34: note:   template argument deduction/substitution failed:
test.cpp:44:24: note:   couldn’t deduce template parameter ‘T’
   44 |     std::cout << *(1 + it) << std::endl;    // compile error!

I don't know why the compiler can't deduce template parameter T. In my point of view it must be trivially long.

Jeongu Kim
  • 117
  • 6
  • 1
    `T` and `N` cannot be deduced from `it`, as per [\[temp.deduct.type\]/5.1](https://timsong-cpp.github.io/cppwp/n4868/temp.deduct.type#5.1) both `T` and `N` are in non-deduced contexts. – dfrib Jun 27 '22 at 14:31
  • Is it because the order of the inputs to the + operator are not reversible? i.e. do you also have to define operator+(array, int) – Loydms Jun 27 '22 at 14:34
  • @dfrib Then can't I use template parameters `T` and `N`? Should I use template parameter `I` for `it` and get `T` manually from `I`? – Jeongu Kim Jun 27 '22 at 14:40
  • 1
    @JeonguKim Make the `operator(int, Iterator)` overload a hidden friend of the (nested) `Iterator` class rather than a free function. Note also that your member `operator+` overload should be const-qualified, but even then it's more common to let binary arithmetic operators to be non-members. [Demo: your example somewhat minimally modified to compile](https://wandbox.org/permlink/y0vgFGraOX3hdRmh). See also [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading). – dfrib Jun 27 '22 at 15:02

0 Answers0