Accessing a Private Class in the << Operator in a Namespace

I have a CFoo class with a private inner CBar class. I want to implement a stream output operator for CFoo, which in turn uses a stream for CBar in the implementation. I can get this to work when CFoo is in a shared namespace, but when I put it in a new namespace (namespace foobar) the operator can no longer access the private inner class. I suspect it has something to do with the full operator signature, but I cannot figure out the correct way to specify the friend declaration and the actual operator declaration so that the compilation is done. Can anyone suggest what I might be losing? Note that it will compile if the stream implementation is made inline in the header, but I don't like exposing the implementation as overkill!

in foobar.h (just comment out usefoobarnamespace to check non-name version):

#define usefoobarnamespace
#ifdef usefoobarnamespace
namespace foobar
{
#endif // usefoobarnamespace
    class CFoo
    {
    public:
        CFoo() {}
        ~CFoo();
        void AddBar();
    private:
        class CBar
        {
        public:
            CBar() {m_iVal = ++s_iVal;}
            int m_iVal;
            static int s_iVal;
        };

        std::vector<CBar*> m_aBars;

        friend std::ostream& operator<<(std::ostream& rcStream, CFoo& rcFoo);
        friend std::ostream& operator<<(std::ostream& rcStream, CFoo::CBar& rcBar);
    };
    std::ostream& operator<<(std::ostream& rcStream, CFoo& rcFoo);
    std::ostream& operator<<(std::ostream& rcStream, CFoo::CBar& rcBar);
#ifdef usefoobarnamespace
}
#endif // usefoobarnamespace

      

and in foobar.cpp:

#ifdef usefoobarnamespace
using namespace foobar;
#endif // usefoobarnamespace

int CFoo::CBar::s_iVal = 0;


CFoo::~CFoo()
{
    std::vector<CBar*>::iterator barIter;
    for (barIter = m_aBars.begin(); barIter != m_aBars.end(); ++barIter)
    {
        delete (*barIter);
    }
}

void CFoo::AddBar()
{
    m_aBars.push_back(new CBar());
}


std::ostream& operator<<( std::ostream& rcStream, CFoo& rcFoo )
{
    rcStream<<"CFoo(";
    std::vector<CFoo::CBar*>::iterator barIter;
    for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
    {
        rcStream<<(*barIter);   
    }
    return rcStream<<")";
}

std::ostream& operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
{
    return rcStream<<"CBar("<<rcBar.m_iVal<<")";
}

      

0


source share


4 answers


Just put the code in the .cpp file in the namespace:



namespace foobar {

// your existing code

}

      

+2


source


You must explicitly list operator definitions in the namespace. (Or fully qualify them with a namespace). As you do this, you declare some <operators (which are in the foobar namespace), then you define some completely new <operators in the global namespace.



namespace foobar
{
    std::ostream& operator<<( std::ostream& rcStream, CFoo& rcFoo )
    {
        rcStream<<"CFoo(";
        std::vector<CFoo::CBar*>::iterator barIter;
        for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
        {
            rcStream<<(*barIter);   
        }
        return rcStream<<")";
    }

    std::ostream& operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
    {
        return rcStream<<"CBar("<<rcBar.m_iVal<<")";
    }
}

      

+2


source


Yours is operator<< functions

now in a namespace foobar

, so you must define them as foobar::operator<<

.

+1


source


This problem can be solved by specializing in namespace overloading of the stream operator:

std::ostream& foobar::operator<<( std::ostream& rcStream, CFoo& rcFoo )
{
    rcStream<<"CFoo(";
    std::vector<CFoo::CBar*>::iterator barIter;
    for (barIter = rcFoo.m_aBars.begin(); barIter != rcFoo.m_aBars.end(); ++barIter)
    {
        rcStream<<(*barIter);   
    }
    return rcStream<<")";
}

std::ostream& foobar::operator<<( std::ostream& rcStream, CFoo::CBar& rcBar )
{
    return rcStream<<"CBar("<<rcBar.m_iVal<<")";
} 

      

By default, the global definitions of these functions are overloaded. They are not friends of the CFoo class and cannot access their private members.

0


source







All Articles