Joris Schellekens
Joris Schellekens

Reputation: 9022

How to overload the operator<< from within a namespace

This is the smallest contained example I can think of. First the header of the class. This class should simply print the one double it contains whenever the << operator is used.

#pragma once
#ifndef EURO_H
#define EURO_H

#include <ostream>

namespace EU
{
   class Euro final
   {
   public:
        explicit Euro(double value);
        virtual ~Euro() = default;

        double getValue() const;

        friend std::ostream& operator<<(std::ostream &os, const Euro &euro);

    private:
        double m_value;
    };
}

#endif // EURO_H

Now the .cpp

#include "euro.h"

using namespace EU;

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

And finally, the main.cpp

#include "euro.h"

#include <iostream>

using namespace EU;

int main()
{
    auto e = Euro(3.14);
    std::cout << e << std::endl;
}

However, when I compile this using:

g++ -std=c++11 *.cpp

it spits out the following error:

/tmp/ccP7OKC5.o: In function `main':
main.cpp:(.text+0x35): undefined reference to `EU::operator<<(std::ostream&, EU::Euro const&)'
collect2: error: ld returned 1 exit status

What am I doing wrong?

Kind regards, Joris

Upvotes: 3

Views: 3458

Answers (2)

Francis Cugler
Francis Cugler

Reputation: 7905

Change your cpp file from this:

#include "euro.h"

using namespace EU;

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

to this:

#include "euro.h"

namespace EU {  

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

} // namespace EU

This defines the code within this cpp file to be within the namespace. What you was previously doing was declaring your namespace to be used at the global scope of that file as you were not defining your source code to be within the namespace.

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

You're expecting using namespace EU; to put all the subsequent code inside namespace EU, but it won't (otherwise your int main would be in the namespace too!). This just brings things already in that namespace into scope.

It means that you're declaring the friend function inside the namespace, but defining a new function in the global scope. Calls to the former will fail because there's no definition for it.

Remove the using namespace, and wrap namespace EU { } around everything in euro.cpp.

Upvotes: 10

Related Questions