Search code examples
c++templatesiteratortypename

operator<< cannot use an IT member of its friend, array


i suppose that, if i make operator<< a friend of a data struct (array by name);

//Forward Declarations
template<typename S, typename T> 
struct array;

template<typename U, typename V>
ostream& operator<< (ostream& ous, const array<U, V>& t);

then, i will be able to do something like this; inside the implementation of operator <<

//operator<< is a friend of struct array{} already
template<typename T, typename U>
ostream& operator<< (ostream& os, const array<T, U>& var){

    if(var){
        /*Error: 'IT' was not declared in this scope*/

        for(IT it = var.data.begin(); it != var.data.end(); it++){
            /*and i thought i need not redeclare IT before using it
             since operator<< is a friend of array already*/
        }
    }
    else{cout << "empty";}

    return os;
}

Now, here is array's implementation:

/*explicit (full) specialization of array for <type, char>*/
template<>
template<typename Key>
struct array<Key, char>{ 

     //data members
     map<const Key, string> data; 
     typedef map<const Key, string>::iterator IT;

     //member function
     friend ostream& operator<< <>(ostream& ous, const array& t);

     //other stuff/functions
};

lastly, the compiler is angry when i test-drove it like this;

void Test(){
     array<int, char> out;
     out[1] = "one";            //Never mind. this has been taken care of
     out[2] = "two";            
     cout << out;               //Error: 'IT' was not declared in this scope
}

Question: what exactly am i doing wrong, or, why can't i dirrectly access and use IT (a typedef within array), even after i had declared operator << (that requests IT) as a friend of the array struct ?


Solution

  • Write

    for( typename array<T, U>::IT it = var.data.begin(); it != var.data.end(); it++){
    

    And change

    typedef map<const Key, string>::iterator IT;
    

    to

    typedef typename std::map<const Key, string>::const_iterator IT;
    

    Here is a demonstrative program where instead of the std::map I used std::array for simplicity. I think it can help you.

    #include <iostream>
    #include <array>
    
    template <typename T, size_t N>
    struct A
    {
        std::array<T, N> a;
    
        typedef typename std::array<T, N>::const_iterator IT;
    };
    
    template <typename T, size_t N>
    std::ostream & operator <<( std::ostream &os, const A<T, N> &a )
    {
        for ( typename A<T, N>::IT it = a.a.begin(); it != a.a.end(); ++it ) os << *it << ' ';
    
        return os;
    }
    
    int main() 
    {
        A<int, 10> a  = { { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } } };
    
        std::cout << a << std::endl;
    
        return 0;
    }
    

    The program output is

    0 1 2 3 4 5 6 7 8 9