Linking error on overloaded operator<<

I have been writing a small static library with a Jeton class. This class has an overloaded operator<<. Here is the code:

In Jeton class:

Jeton.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace pXbase{

class Jeton
{
public:
    // Some stuff...

    friend std::ostream& operator<<(std::ostream& p_flux, const Jeton& p_jeton);

private:
    Couleur m_couleur;
};

} // namespace pXbase 


Jeton.cpp:
1
2
3
4
5
6
7
8
9
10
11
using namespace pXbase;
using namespace std;

//Some stuff...

ostream& operator<<(ostream& p_flux, const Jeton& p_jeton)
{
    p_flux << " " << p_jeton.imprimerCodeConsole() << " "; // The method returns a char.

    return p_flux;
}


And finally, main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Jeton.h"

using namespace pXbase;
using namespace std;

int main()
{
    Jeton jeton;

    cout << jeton;

    return 0;
}


When I compile this, I get the following liker error:


undefined reference to `pXbase::operator<<(std::ostream&, pXbase::Jeton const&)'


I have carefully looked at the code but found nothing that could generate this error... My library is correctly liked to the main since every other method work. Can anyone tell me what is wrong with this?

Thanks!
Last edited on
Try enclosing the code in file Jeton.cpp inside the namespace pXbase.
@Chervil: Thanks, it did work with your suggestion. But... what's going on here? It did enclose the operator in the pXbase namespace upon declaration. Why do I have to do it it at definition as well?
I'm not sure of the proper technical explanation, however, as you said, the function was declared within that namespace, so it seems reasonable that the definition should be too. Otherwise it would belong to the global namespace.
Ok thanks!
@BobMorane: I was trying to replicate your code and am getting error messages from the header and implementation files compilations:

error: 'ostream' in namespace 'std' does not name a type

I think I understand why this is happening, at least in the header file - Jeton is enclosed entirely within namespace pXbase and therefore cannot reach namespace std despite the scope resolution std::ostream. Did you face any similar issues?
@gunnerfunner: Thanks for the check. I did not see that error message here. After I applied Chervil's suggestion, everything compiled/linked fine. Also, I think it's worth mentioning that my compiler (gcc) is set to see warning as errors.

Personnaly,

Jeton is enclosed entirely within namespace pXbase and therefore cannot reach namespace std despite the scope resolution std::ostream.


I don't think this should be. You can refer to other namespaces inside a particular namespace. Maybe I don't understand your point precisely?

Thanks
Last edited on
@gunnerfunner

Did you put #include <iostream> at the start of Jeton.h ?
No, I knew #include <iostream> might be a possible solution but did not want to do that in the header file. But it seems OP managed to get by w/o it
@gunnerfunner: is it working now?
Well, if the header uses something like std::ostream then it must have the <iostream> header available. I can't see a problem with putting it at the start of "Jeton.h", but if you don't, you need to make sure that whichever file makes use of header "Jeton.h" first includes the required standard headers.
if the header uses something like std::ostream then it must have the <iostream> header available ... not always but in this case, sure because of namespace pXbase. I was just wondering if we could do w/o including the whole library in the header but it seems we can't for this example
The program won't compile if there is a reference to std:: something without having the corresponding header available somewhere. Sometimes one header includes another, so it isn't always obvious which headers are visible.

User-defined headers are generally included inside another file, which might incidentally include some other headers, but one way or another that's the only way it can compile.
> I was just wondering if we could do w/o including the whole library in the header

To minimise dependencies:

In the header: #include <iosfwd> and declare the functions

In the implementation file: #include <iostream> (plus #include <fstream> etc. as required) and define the functions.

eg. header file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// #include guard 
#include <iosfwd>

namespace A
{
    struct B
    {
        B() = default ;
        B( std::ifstream& ) ;

        int v = 7 ;
        // ...
        friend std::ostream& operator<< ( std::ostream& stm, const B& b ) ;
    };
}


implementation file:
1
2
3
4
5
6
7
8
9
10
11
// #include "header file"
#include <iostream>
#include <fstream>

namespace A
{
    B::B( std::ifstream& file ) { if( !( file >> v ) ) { /* throw something */ }}

    std::ostream& operator << ( std::ostream& stm, const A::B& b )
    { return stm << "B{ " << b.v << " }\n" ; }
}
@JLBorges: Brilliant! Thank you
Topic archived. No new replies allowed.