c++boostmakefileboost-test

BOOST Test: How to handle << operator redefinition to print the same type in different tests?


The Problem

Given the following 2 test files in BOOST Test (very simplified compared to my real example for MRE)

Foo.cpp

#define BOOST_TEST_MODULE FooTest
#include <boost/test/included/unit_test.hpp>
#include <iostream>

#include "enumToPrint.hpp"

std::ostream& operator<<(std::ostream& os, const EnumToPrint& e) {
    switch(e) {
        case EnumToPrint::Any:
            os << "Any";
            break;
        case EnumToPrint::Some:
            os << "Some";
            break;
        default:
            os << "Unknown";
            break;
    }
    return os;
}

BOOST_AUTO_TEST_CASE(MyTestFoo)
{
    EnumToPrint e = EnumToPrint::Any;
    BOOST_CHECK_EQUAL(e, EnumToPrint::Any);
}

and

Bar.cpp

#define BOOST_TEST_MODULE BarTest
#include <boost/test/included/unit_test.hpp>
#include <iostream>

#include "enumToPrint.hpp"

std::ostream& operator<<(std::ostream& os, const EnumToPrint& e) {
    switch(e) {
        case EnumToPrint::Any:
            os << "Any";
            break;
        case EnumToPrint::Some:
            os << "Some";
            break;
        default:
            os << "Unknown";
            break;
    }
    return os;
}

BOOST_AUTO_TEST_CASE(MyTestBar)
{
    EnumToPrint b = EnumToPrint::Some;
    BOOST_CHECK_EQUAL(b, EnumToPrint::Some);
}

When I run make test I get

/usr/bin/ld: obj/BoardReset.o: in function `boost::unit_test::output::xml_report_formatter::do_confirmation_report(boost::unit_test::test_unit const&, std::ostream&)':
/usr/include/boost/test/impl/xml_report_formatter.ipp:104: multiple definition of `boost::unit_test::output::xml_report_formatter::do_confirmation_report(boost::unit_test::test_unit const&, std::ostream&)'; obj/BoardFEN.o:/usr/include/boost/test/impl/xml_report_formatter.ipp:104: first defined here

Not sure how to proceed because If I remove it in one, of them then it says I am missing the stream definition. If I make a dedicated header file with the ostream functions then include this file in each test.cpp then I still get the same error.

Things I have tried

/usr/include/c++/9/iomanip:363:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Put_time<_CharT>)’
  363 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Put_time<_CharT> __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:363:5: note:   template argument deduction/substitution failed:

Solution

  • Add the declaration into "enumToPrint.hpp":

    std::ostream& operator<<(std::ostream& os, const EnumToPrint& e);
    

    Remove one of the definitions from either Foo.cpp or Bar.cpp. Or yet better move that definition into "enumToPrint.cpp".