Search code examples
c++namespacesoperator-overloadingfriend

friend can't access private members using namespace


I'm getting the following errors when using MS Visual Studio 2019 when overloading operator<<:

Severity    Code    Description Project File    Line    Suppression State
Error   C2248   'Instruction::Device_Impedance::m_minimum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace    device_impedance.cpp    13  
Severity    Code    Description Project File    Line    Suppression State
Error   C2248   'Instruction::Device_Impedance::m_maximum_ohms': cannot access private member declared in class 'Instruction::Device_Impedance' friend_ostream_namespace    device_impedance.cpp    14  

device_impedance.hpp:

#ifndef INSTRUCTION_DEVICE_IMPEDANCE_HPP
#define INSTRUCTION_DEVICE_IMPEDANCE_HPP

#include <string>
#include <iostream>


namespace Instruction
{

class Device_Impedance
{
public:
    Device_Impedance();

    Device_Impedance(const unsigned int min_ohms,
                     const unsigned int max_ohms);
       
    //! Constructor -- Copy
    Device_Impedance(const Device_Impedance&  di);
    
    //! Destructor
    ~Device_Impedance();

public:
    Device_Impedance&
    operator=(const Device_Impedance& di);

    friend std::ostream& operator<< (std::ostream& out, const Instruction::Device_Impedance&   di);
   

    //--------------------------------------------------------------------------
    //  Public Methods
    //--------------------------------------------------------------------------
public:
    const std::string&      get_name() const override;
    
    //--------------------------------------------------------------------------
    //  Private Members
    //--------------------------------------------------------------------------
private:
    unsigned int    m_minimum_ohms;
    unsigned int    m_maximum_ohms;
};


}   // End namespace Instruction

/*! @}  // End Doxygen Group
 */

#endif // INSTRUCTION_DEVICE_IMPEDANCE_HPP  

device_impedance.cpp

#include "device_impedance.hpp"

using namespace Instruction;


/*!
 *  \details    Output the instruction name to the stream.
 */
std::ostream&
operator<< (std::ostream& out, const Instruction::Device_Impedance&   di)
{
        out << di.get_name()
//***** The next two lines are causing the error.
            << "    " << di.m_minimum_ohms
            << ", "   << di.m_maximum_ohms
            << "\n";

    return out;
}


const std::string&
Device_Impedance ::
get_name() const
{
    static std::string  instruction_name{"DEVICE_IMPEDANCE"};
    return instruction_name;
}

Do I have the namespace syntax correct for the implementation of operator<<?


Solution

  • No, your syntax is incorrect. using namespace does not cause the following declarations/definitions to inhabit that namespace.

    Either use namespace Instruction { /*definition of operator<< here*/ } like you do in the header or qualify the name in the definition:

    std::ostream&
    Instruction::operator<< (std::ostream& out, const Instruction::Device_Impedance&   di)
    

    (It seems that this is now intended to not be allowed anymore and GCC soft-rejects it by warning and rejecting with -pedantic-errors, see comments below.)

    Otherwise you are defining the global ::operator<< overload, not the friended one that inhabits in the namespace enclosing the class, i.e. in Instruction.

    What using namespace does however achieve is that you won't have to qualify names for the purpose of lookup, so e.g. Instruction:: in the function parameter is redundant with it. The same is also true in the declaration in the class.


    Also, as noted in the question comments override on get_name is also wrong, because this function isn't actually an override.