2014-08-11 5 views
1

У меня небольшая проблема, и я работаю над ней несколько часов, но не могу найти решение. Надеюсь, ты поможешь мне.итераторы в C++ template 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;} 

}; 

А вот 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; 
} 

Первый cout работает отлично, но линия, которая комментируется дает это: error: no matching function for call to ‘Array<double>::printBegin(Array<int>::Iterator)’

Я не» t понять, потому что последняя строка в моем классе Array соответствует (обычно) для этой функции вызова

+1

Я нашел [этот ответ по другому вопросу] (http://stackoverflow.com/a/6569653/2507444), который описывает проблемы с попыткой автоматического вывода аргумента функции шаблона с помощью вложенного класса (например, вашего массива :: Итератор'). Также обратите внимание, что вы можете явно указать аргумент шаблона, и он будет работать - 'cout << p.printBegin (x.begin());'. –

+2

Кажется, что E не может быть выведен автоматически. Попробуйте это так: 'cout << p.printBegin (x.begin());' – Simon

+0

Возможный дубликат [Почему вы не используете здесь аргумент аргумента шаблона?] (Http://stackoverflow.com/questions/ 1268504/why-is-the-template-argument-deduction-not-working-here) –

ответ

1

Проблема в том, что вы хотите вывести E в Array<E>::Iterator от x.begin(), который является Array<int>::Iterator. Но это просто невозможно.

Ваш лучший вариант, вероятно, написать:

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

Если по какой-либо причине, вы должны использовать E тип, то лучше добавить вложенную ЬурейеЕ:

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

И потом:

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

Подождите! Ваш итератор происходит от std::iterator, поэтому typedef уже существует. Нет необходимости переопределять:

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

Спасибо и спасибо всем! Это было полезно – Gio

0

Ваш вопрос очень похож на другой вопрос о вычитании шаблона.

Компилятор не может вычитать тип E от Array<E>::Iterator. Зачем это нужно? Два разных типа E могут использовать один и тот же тип итератора.

То, что вы действительно говорите компилятор:

«Есть тип„Е“, для которого Array<E>::Iterator этого типа?»