1

I have a little problem and I'm working on it for several hours but can't find a solution. Hope you will help me.

Here is my class:

#include <iostream>
#include <iterator>

template <typename T> class Array{
private:
    size_t size;
    T *newArray;

public:
    class Iterator:public std::iterator<std::output_iterator_tag, T>{
        T *p;
        public:
            Iterator(T*x):p(x){}
            T& operator*() {return *p;}

    };

    Array (size_t size = 10): size(size), newArray(new T[size]){};
    Iterator begin(){return (Iterator(newArray));}

    T printBegin(typename Array<T>::Iterator it){ return *it;}

    template <typename E>
    T printBegin(typename Array<E>::Iterator it){ return (T)*it;}

};

And here is Main:

using namespace std;

int main(){

    Array<int> x;
    Array<int> y;
    cout << y.printBegin(x.begin()); // prints 0 OK

    Array<double> p;
    // cout << p.printBegin(x.begin());

    return 0;
}

The first cout works fine but the line that is commented gives this : error: no matching function for call to ‘Array<double>::printBegin(Array<int>::Iterator)’

I don't understand because the last line in my Array class matches (normally) for this function call

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
v37
  • 57
  • 1
  • 6
  • 1
    I found [this answer on another question](http://stackoverflow.com/a/6569653/2507444) that describes issues with trying to automatically deduce the a template function argument using a nested class (such as your `Array::Iterator`). Also note that you can explicitly specify the template argument and it will work - `cout << p.printBegin(x.begin());`. – Peter Clark Aug 11 '14 at 13:44
  • 2
    It seems, that E cannot be deduced automatically. Try it this way: `cout << p.printBegin(x.begin());` – Simon Aug 11 '14 at 13:44
  • possible duplicate of [Why is the template argument deduction not working here?](http://stackoverflow.com/questions/1268504/why-is-the-template-argument-deduction-not-working-here) – n. m. could be an AI Aug 11 '14 at 13:55
  • Your class doesn't make any sense whatsoever. Why should the `Array` class know how to print itself? Why should it be able to print other arrays other than its own? Why are you not using `std::array` or `std::vector` together with `std::copy`/`std::back_inserter` or a simple `for` loop to print the elements out on `std::cout`? Do you have a Java background? – Shoe Aug 11 '14 at 14:01
  • [OT]: You should avoid C-cast. – Jarod42 Aug 11 '14 at 14:32

2 Answers2

1

The problem is that you want to deduce the E in Array<E>::Iterator from x.begin() that is an Array<int>::Iterator. But that is simply not possible.

Your best option is probably to write:

template <typename IT>
T printBegin(IT it){ return (T)*it;}

If, for any reason, you need to use the E type, then it is better to add a nested typedef:

class Iterator:public std::iterator<std::output_iterator_tag, T>{
    public:
        typename T array_member_type;
        //...
};

And then:

template <typename IT>
T printBegin(IT it){
    typedef typename IT::array_member_type E;
    return (T)*it;
}

Wait! Your iterator derives from std::iterator so the typedef already exists. No need to redefine:

template <typename IT>
T printBegin(IT it){
    typedef typename IT::value_type E;
    return (T)*it;
}
rodrigo
  • 94,151
  • 12
  • 143
  • 190
0

Your question is very similar to another question about template deduction.

The compiler cannot deduct the type E from Array<E>::Iterator. Why should it be able to? Two different types E could share the same iterator type.

What you are really saying to the compiler is:

"Is there a type "E" for which Array<E>::Iterator is this type?"

CashCow
  • 30,981
  • 5
  • 61
  • 92