BOOST Test:如何处理<<运算符重定义以在不同测试中打印同一类型?
BOOST Test 多测试文件编译冲突问题
问题描述
在BOOST Test环境下有两个简化后的测试文件:
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); }
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); }
执行make test时触发链接错误:
/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
若移除其中一个文件的<<运算符定义,编译器会提示缺少流输出重载;即使把该函数放到专用头文件并在测试文件中包含,依旧出现相同的重复定义错误。
已尝试的方法
- 将ostream重载函数放入头文件并在测试文件中包含,报错依旧;尝试添加
inline修饰也无效 - 移除其中一个测试文件的ostream定义,出现ostream缺失错误:
/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:
问题分析
- 测试框架重复定义:使用
#include <boost/test/included/unit_test.hpp>会把BOOST Test的完整实现代码直接嵌入每个测试源文件,编译后每个目标文件都包含一份框架实现,链接时就会触发重复定义错误。 - 运算符重载作用域与重复定义:枚举的
operator<<重载如果未正确通过inline和头文件防护避免重复实例化,或者未放在枚举所在命名空间导致ADL(参数依赖查找)失效,就会出现要么重复定义、要么找不到重载的矛盾。
解决方案
1. 调整BOOST Test头文件引用
把测试文件中的#include <boost/test/included/unit_test.hpp>替换为#include <boost/test/unit_test.hpp>,该头文件仅包含框架声明,实现代码通过链接库提供。
2. 正确实现ostream重载
修改enumToPrint.hpp,添加头文件防护和inline关键字确保重载函数仅实例化一次:
#ifndef ENUM_TO_PRINT_HPP #define ENUM_TO_PRINT_HPP #include <iostream> enum class EnumToPrint { Any, Some }; inline 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; } #endif
之后删除测试文件中重复的operator<<定义,测试文件仅保留测试逻辑即可。
3. 编译链接调整
链接时需要手动指定BOOST Test库,示例编译命令:
# 编译目标文件 g++ -c Foo.cpp -o Foo.o g++ -c Bar.cpp -o Bar.o # 链接生成可执行测试程序 g++ Foo.o -o FooTest -lboost_unit_test_framework g++ Bar.o -o BarTest -lboost_unit_test_framework
内容的提问来源于stack exchange,提问作者hexaquark
相关产品推荐
相关产品推荐

