Where to put overload<< code? - c++

I am trying to overload the stream operator <<, for a class Foo which has already a toString() function returning a string, with the following code:
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
In order to use it in a main.cppfile
My question is: Where to put that piece of code?
If I place it in the main.cpp, before its usage, it works well, but i may want to use it in other files.
If I place it in foo.cpp, I get a 'no such function' error:
src/main.cpp:77: error: no match for ‘operator<<’ in ‘std::cout << foo’
which make sense since the code is not included to the main.cpp file
If I place it in the foo.hclass header, outside class declaration, I get a 'multiple definition' error:
foo.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Foo const&)':
foo.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Matrix const&)'
bar.o:bar.cpp:(.text+0x0): first defined here
The foo.h header is indeed included in different classes/files, but there is a ifdef guard, so I don't understand this.
So How should I do?

There are multiple options:
Declare it in the header, after Foo, and define it in Foo.cpp.
//foo.h
class Foo
{};
std::ostream &operator<<( std::ostream &s, Foo const& foo );
//foo.cpp
#include "foo.h"
std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
Define it as a friend inside the class definition.
//Foo.h
class Foo
{
friend std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
};
Define it in the header, outside the class definition, and mark it as inline to prevent the multiple definition.
//Foo.h
class Foo
{
};
inline std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}

Put the prototype of the overload by the class declaration, the implementation thereof at the Foo implementation (or if you want it inline, put it at the Foo declaration).
So either:
// foo.h
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
std::ostream& operator<< (std::ostream &, Foo const &);
#endif // FOO_H_ASDSADKJSLADJL
// foo.cpp
#include "foo.h"
....
std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
or
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
inline std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
#endif // FOO_H_ASDSADKJSLADJL
Your error of the compiler not finding it was the lack of a prototype of your overload.

Put the declaration in the header file, and the definition in the cpp file.
That is, put
std::ostream &operator<<( std::ostream &flux, Foo const& foo );
in your header file, and put
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
in your cpp file.
This way, you can include the header file wherever you want, and things can use the function, but it will only be defined once, so you won't get the multiple definitions error.

Declare it in the header, where you declare Foo, define it in the source, where you define Foo methods.

As ususal with C and C++, you should
put the actual code into the appropriate .c / .cpp file - here I would recommend foo.cpp
put a predeclaration into the appropriate .h/.hpp header file, with an appropriate #ifdef guard for everything that is used from outside the main c/cpp file.
In some situations, you can use a #define macro, or an inline function. This should then be done in the header; there shouldn't be a multiple declaration error because of the inlining.
Technically you can do a lot of things. I recommend sticking to the best practise of defining the API in the header file, and putting the implementation into the code file. This is most extensible. The inline hack will work for this case, but if you at some later point decides to enhance the method and remove the inline, it will surprisingly break.
The header / code split is least likely to break.

Related

Use non-member functions in Qt [duplicate]

Given this code sample:
complex.h :
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
class Complex
{
public:
Complex(float Real, float Imaginary);
float real() const { return m_Real; };
private:
friend std::ostream& operator<<(std::ostream& o, const Complex& Cplx);
float m_Real;
float m_Imaginary;
};
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
#endif // COMPLEX_H
complex.cpp :
#include "complex.h"
Complex::Complex(float Real, float Imaginary) {
m_Real = Real;
m_Imaginary = Imaginary;
}
main.cpp :
#include "complex.h"
#include <iostream>
int main()
{
Complex Foo(3.4, 4.5);
std::cout << Foo << "\n";
return 0;
}
When compiling this code, I get the following error:
multiple definition of operator<<(std::ostream&, Complex const&)
I've found that making this function inline solves the problem, but I don't understand why. Why does the compiler complain about multiple definition? My header file is guarded (with #define COMPLEX_H).
And, if complaining about the operator<< function, why not complain about the public real() function, which is defined in the header as well?
And is there another solution besides using the inline keyword?
The problem is that the following piece of code is a definition, not a declaration:
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
You can either mark the function above and make it "inline" so that multiple translation units may define it:
inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
Or you can simply move the original definition of the function to the "complex.cpp" source file.
The compiler does not complain about "real()" because it is implicitly inlined (any member function whose body is given in the class declaration is interpreted as if it had been declared "inline"). The preprocessor guards prevent your header from being included more than once from a single translation unit ("*.cpp" source file"). However, both translation units see the same header file. Basically, the compiler compiles "main.cpp" to "main.o" (including any definitions given in the headers included by "main.cpp"), and the compiler separately compiles "complex.cpp" to "complex.o" (including any definitions given in the headers included by "complex.cpp"). Then the linker merges "main.o" and "complex.o" into a single binary file; it is at this point that the linker finds two definitions for a function of the same name. It is also at this point that the linker attempts to resolve external references (e.g. "main.o" refers to "Complex::Complex" but does not have a definition for that function... the linker locates the definition from "complex.o", and resolves that reference).
Move implementation to complex.cpp
Right now after including this file implementation is being compiled to every file.
Later during linking there's a obvious conflict because of duplicate implementations.
::real() is not reported because it's inline implicitly (implementation inside class definition)
I was having this problem, even after my source and header file were correct.
It turned out Eclipse was using stale artifacts from a previous (failed) build.
To fix, use Project > Clean then rebuild.
An alternative to designating a function definition in a header file as inline is to define it as static. This will also avoid the multiple definition error.

Operator overloading on the global scope in qt/c++ is giving me the multiple definition compile error [duplicate]

Given this code sample:
complex.h :
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
class Complex
{
public:
Complex(float Real, float Imaginary);
float real() const { return m_Real; };
private:
friend std::ostream& operator<<(std::ostream& o, const Complex& Cplx);
float m_Real;
float m_Imaginary;
};
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
#endif // COMPLEX_H
complex.cpp :
#include "complex.h"
Complex::Complex(float Real, float Imaginary) {
m_Real = Real;
m_Imaginary = Imaginary;
}
main.cpp :
#include "complex.h"
#include <iostream>
int main()
{
Complex Foo(3.4, 4.5);
std::cout << Foo << "\n";
return 0;
}
When compiling this code, I get the following error:
multiple definition of operator<<(std::ostream&, Complex const&)
I've found that making this function inline solves the problem, but I don't understand why. Why does the compiler complain about multiple definition? My header file is guarded (with #define COMPLEX_H).
And, if complaining about the operator<< function, why not complain about the public real() function, which is defined in the header as well?
And is there another solution besides using the inline keyword?
The problem is that the following piece of code is a definition, not a declaration:
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
You can either mark the function above and make it "inline" so that multiple translation units may define it:
inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
Or you can simply move the original definition of the function to the "complex.cpp" source file.
The compiler does not complain about "real()" because it is implicitly inlined (any member function whose body is given in the class declaration is interpreted as if it had been declared "inline"). The preprocessor guards prevent your header from being included more than once from a single translation unit ("*.cpp" source file"). However, both translation units see the same header file. Basically, the compiler compiles "main.cpp" to "main.o" (including any definitions given in the headers included by "main.cpp"), and the compiler separately compiles "complex.cpp" to "complex.o" (including any definitions given in the headers included by "complex.cpp"). Then the linker merges "main.o" and "complex.o" into a single binary file; it is at this point that the linker finds two definitions for a function of the same name. It is also at this point that the linker attempts to resolve external references (e.g. "main.o" refers to "Complex::Complex" but does not have a definition for that function... the linker locates the definition from "complex.o", and resolves that reference).
Move implementation to complex.cpp
Right now after including this file implementation is being compiled to every file.
Later during linking there's a obvious conflict because of duplicate implementations.
::real() is not reported because it's inline implicitly (implementation inside class definition)
I was having this problem, even after my source and header file were correct.
It turned out Eclipse was using stale artifacts from a previous (failed) build.
To fix, use Project > Clean then rebuild.
An alternative to designating a function definition in a header file as inline is to define it as static. This will also avoid the multiple definition error.

Defining a custom equality operator in an anonymous namespace

I have a C-struct (in a C header file) that looks like so:
struct Foo {
int a;
int b;
int c;
};
typedef struct Foo Foo;
I want to test equality of two vectors of these structs, and so I would like to define a custom equality operator for this struct for just my translation unit.
I am able to do so with
static inline bool operator==(const Foo&, const Foo&) {...}
but not with
namespace {
bool operator==(const Foo&, const Foo&) {...}
}
Why can the equality template for std::vector not find this operator, and is there a better way than tossing a static inline in the global namespace?
I think you'll find that std::vector actually does find the operator in the anonymous namespace, if that operator's declaration occurs before #include <vector>.
The reason it doesn't find it in your code is related to the two-phase lookup for names in template functions. The first phase finds candidates in all namespaces in scope. The second phase only finds dependent names. "Argument-dependent lookup" which searches the namespace containing the type is dependent just as the phrase says. Lookup in the anonymous namespace is not dependent, so it won't be done during the second phase.
See also:
Declare function after template defined
Template specialization doesn't see a function in its point of instantiation
Why does the compiler find my function if is not yet declared?
The first thing to be noted is that an anonymous namespace is not the same as no namespace.
namespace
{
bool operator==(const Foo&, const Foo&) {...}
}
is really something like
namespace ANameUniqueToTheFile
{
bool operator==(const Foo&, const Foo&) {...}
}
using ANameUniqueToTheFile;
with the downside that the language does not give you the ability to get the name of the namespace.
For that reason, the operator== function defined in the anonymous namespace is not found using ADL.
I can see why you would want to put the operator== function in a namespace. One possbile way to do that would be to #include the .h file that defines the struct inside a named namespace.
FooWrapper.h:
namespace MyApp
{
#include "foo.h"
// Declare the function.
bool operator==(Foo const& lhs, Foo const& rhs);
}
FooWrapper.cpp
#include "FooWrapper.h"
namespace MyApp
{
// Implement the function.
bool operator==(Foo const& lhs, Foo const& rhs) { ... }
}
However...
I realize that I'm simplifying a bit about what's in "foo.h". Adding all of them in namesapce MyApp might not be appropriate, specially if "foo.h" includes other .h files and/or standard header files. I am hoping it gives you some ideas on how to tackle the problem.
If putting all of "foo.h" in namespace MyApp does not work smoothly, it will probably be expedient to define the operato== function in global scope.

Multiple definition of function (in derived class) [duplicate]

Given this code sample:
complex.h :
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
class Complex
{
public:
Complex(float Real, float Imaginary);
float real() const { return m_Real; };
private:
friend std::ostream& operator<<(std::ostream& o, const Complex& Cplx);
float m_Real;
float m_Imaginary;
};
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
#endif // COMPLEX_H
complex.cpp :
#include "complex.h"
Complex::Complex(float Real, float Imaginary) {
m_Real = Real;
m_Imaginary = Imaginary;
}
main.cpp :
#include "complex.h"
#include <iostream>
int main()
{
Complex Foo(3.4, 4.5);
std::cout << Foo << "\n";
return 0;
}
When compiling this code, I get the following error:
multiple definition of operator<<(std::ostream&, Complex const&)
I've found that making this function inline solves the problem, but I don't understand why. Why does the compiler complain about multiple definition? My header file is guarded (with #define COMPLEX_H).
And, if complaining about the operator<< function, why not complain about the public real() function, which is defined in the header as well?
And is there another solution besides using the inline keyword?
The problem is that the following piece of code is a definition, not a declaration:
std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
You can either mark the function above and make it "inline" so that multiple translation units may define it:
inline std::ostream& operator<<(std::ostream& o, const Complex& Cplx) {
return o << Cplx.m_Real << " i" << Cplx.m_Imaginary;
}
Or you can simply move the original definition of the function to the "complex.cpp" source file.
The compiler does not complain about "real()" because it is implicitly inlined (any member function whose body is given in the class declaration is interpreted as if it had been declared "inline"). The preprocessor guards prevent your header from being included more than once from a single translation unit ("*.cpp" source file"). However, both translation units see the same header file. Basically, the compiler compiles "main.cpp" to "main.o" (including any definitions given in the headers included by "main.cpp"), and the compiler separately compiles "complex.cpp" to "complex.o" (including any definitions given in the headers included by "complex.cpp"). Then the linker merges "main.o" and "complex.o" into a single binary file; it is at this point that the linker finds two definitions for a function of the same name. It is also at this point that the linker attempts to resolve external references (e.g. "main.o" refers to "Complex::Complex" but does not have a definition for that function... the linker locates the definition from "complex.o", and resolves that reference).
Move implementation to complex.cpp
Right now after including this file implementation is being compiled to every file.
Later during linking there's a obvious conflict because of duplicate implementations.
::real() is not reported because it's inline implicitly (implementation inside class definition)
I was having this problem, even after my source and header file were correct.
It turned out Eclipse was using stale artifacts from a previous (failed) build.
To fix, use Project > Clean then rebuild.
An alternative to designating a function definition in a header file as inline is to define it as static. This will also avoid the multiple definition error.

is it possible to override the c++ operator<< for a struct in a header file?

I am trying to print out the fields in a struct by overriding operator<<. This works fine if I place the override in a cpp file, however I would like to have it in my header file.
However when I do, I get the error:
multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, test)'
Is it possible to have in the header file?
test.h
#ifndef TEST_H
#define TEST_H
struct test{
int a;
int b;
int c;
};
std::ostream& operator<< (std::ostream& o, const test& t){
o <<"{ " << t.a << " }" << endl;
return o;
}
#endif
As with any function, if you define it in a header, make it inline:
inline std::ostream& operator<< (std::ostream& o, const test& t)
^^^^^^
This relaxes the One Definition Rule, allowing a definition in any translation unit that includes the header.