0

I have code with the following basic structure:

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
            public:
            template<class T,unsigned DIM>
            friend std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);
        }    

    };

}

The initial problem was to get my operator<< outside the namespace A.

I tried this solution : How do I define friends in global namespace within another C++ namespace?

namespace A{

    template<class T,unsigned DIM>
    class CMyTable;
}

template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
            public:
            template<class T,unsigned DIM>
            friend std::ostream& ::operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);
        }    

    };

}

template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec){
// [...]
}

I got this error : error C2063: 'operator <<' : not a function inside the class declaration.

public:
template<class T,unsigned DIM>
friend std::ostream& ::operator<<(std::ostream& s, const CMyTable<T,DIM>& 

Does anyone have any ideas ?

Thanks.

Community
  • 1
  • 1
Haimo
  • 43
  • 5

2 Answers2

0

Output operator is interface of class really, so, logically, it should be in namespace, where class is declared, but for make your code work, you can use

namespace A{

    template<class T,unsigned DIM>
    class CMyTable;
}

// friend is not correct here.
template<class T,unsigned DIM>
/*friend*/ std::ostream& operator<<(std::ostream& s, const A::CMyTable<T,DIM>& vec);

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
            public:
            // choose another names of template pars.
            // or use
            //friend std::ostream& (::operator << <>)(std::ostream& s,
            //const CMyTable<T, DIM>&);
            /*template<class T,unsigned DIM>*/
            template<class U, unsigned D>
            friend std::ostream& (::operator <<)(std::ostream&,
            const CMyTable<U,D>&);
        };
}

template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const A::CMyTable<T,DIM>& vec){
// [...]
}
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • For the friend, it was a mistake in the post. I edited the post. I changed the names of template arguments but still got the same error: 'operator <<' not a function. – Haimo Apr 19 '13 at 08:35
  • @Haimo look at code well... Note: `friend std::ostream& **(**::operator <<**)**` – ForEveR Apr 19 '13 at 08:37
  • Sorry, I actually copied/pasted your code. So i added the parenthesis too. But still not work... – Haimo Apr 19 '13 at 08:43
  • @Haimo, i don't know, why you get this error. Look at example - it works well as you seen. – ForEveR Apr 19 '13 at 09:03
  • Is that possible my compiler (I'm working with VS2005) put me into this ? – Haimo Apr 19 '13 at 09:13
0

If your ostream overload has to be a friend (needs access to protected members) then define it inline so that you can use the template arguments passed to the class.

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
        public:
        // template<class T,unsigned DIM>  // This will shadow otherwise
        friend std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec) {
        // [...]
        }
    };
}

Otherwise completely remove its declaration from the class and namesapce and just define it outside as a templated overload.

Remember it doesn't have to be friend if it doesn't need access to private or protected elements.

namespace A{
   template<class T,unsigned DIM>
   class CMyTable{
    ...
        public:
    };
}



template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const A::CMyTable<T,DIM>& vec){
// [...]
}

The third option is to keep it friend but define it inside namespace A

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        public:
            int i;

        template<class V,unsigned E>
        friend std::ostream& operator<<(std::ostream& s, const CMyTable<V,E>& vec);
    };  

};
//
//

namespace A{

    template<class T,unsigned DIM>
    std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec) {
        s << vec.i;
    }

}
stardust
  • 5,918
  • 1
  • 18
  • 20
  • Thanks for your answer. But I need my method to be friend. I just don't want to define accessors (even const) in my class. – Haimo Apr 19 '13 at 09:10
  • @Haimo then what is the problem with defining it inline (inside the class)? – stardust Apr 19 '13 at 09:12
  • I want to access to the operator in the global namespace. – Haimo Apr 19 '13 at 09:15
  • @Haimo Here http://coliru.stacked-crooked.com/view?id=607c22b9a37c4e7aefe63bae25e87bd1-50d9cfc8a1d350e7409e81e87c2653ba – stardust Apr 19 '13 at 09:20
  • @Haimo OK if you want not to define it inline for some reason then you have to define it in namespace A. See the edit. Third option. – stardust Apr 19 '13 at 09:29
  • Ok, thanks. I will check if it will be ok if I use the operator in another namespace (not the global namespace). – Haimo Apr 19 '13 at 09:30