Locally redefining the implementation of a global function in C++

213 Views Asked by At

I am writing some testing code for an existing C++ application by writing a file with a main() function and some helper classes, and linking it to the object files of the application's other classes. I do not have access to the source files, only to the headers and objects/libraries, which I cannot modify.

In my test code I want to output a subset of fields of a huge structure. Unfortunately, there is already a global ostream& operator<<(ostream&, HugeStruct const&) function in the existing code, which dumps everything. The function is declared in the HugeStruct's header file and implemented in the corresponding source.

Is there a way to override that function only in the testing source without having the compiler and/or linker throw a fit? It is compiled with GCC 4.8.5.

EDIT:

Yes, there are workarounds that I can use.

I could use a print function (as suggested in the comments), but I like the convenience of chaining the << operators.

I can write a std::string out(HugeStruct const&) function that will output the fields to a string and use os << out(hs). This is what I currently do, but it feels like a roundabout way.

Still, I find the question interesting in the general case.

1

There are 1 best solutions below

2
Jan15 On

If you can modify the header, to truly override the implementation, you could:

  • mark the ostream& operator<<(ostream&, HugeStruct const&) as inline
  • implement ostream& operator<<(ostream&, HugeStruct const&) in a cpp
  • make sure your cpp with new implementation comes after the old object file in the link command

How this works:

  • inline tells the linker to not complain if it finds multiple definitions
  • the C++ standard says it's undefined behavior if you do what I told you.
    • this means the programmer (you) cannot expect a correct program if you do that
    • practically though, (all?) linkers process the symbols left to right and override the implementation

I do not recommend this :) the out function is safer.

Another option I see is to use overload resolution: You have to make sure your local operator<< is a better match than the library provided one.

You can do that by for example deriving from the ostream you use in your test file. Here I will assume you use std::cout.

struct TestCout: public std::ostream{
// ...
};

TestCout& operator<<(TestCout& os, HugeStruct const&);

TestCout tcout;
tcout << huge_struct;