我在一个“大”跨平台项目中使用easyloggingpp 。足够大,以至于我无法创建一个简单的运行示例来重现我将要描述的行为。
所以我enum
在一些标题中定义了一些类型,比如说:
在types.h
:
typedef enum MyEnum
{
First,
Second
} MyEnum;
枚举是一个
C
枚举,因为该项目是 ABI 安全的,并且 API 是 C 函数和类型的薄层(我们对沙漏模式的实现)
它还有两个处理打印的函数,假设这些是函数(实际上只有函数的主体不同):
inline std::ostream & operator << (std::ostream & out, MyEnum value)
{
return out << get_string(value);
}
在types.cpp
中,我有:
namespace MyNamespace
{
const char* get_string(MyEnum value)
{
assert(0);
}
}
如果我在我的代码中调用这样的东西
MyEnum x = First;
std::stringstream os;
os << "Value of x is: " << x;
函数中的assert(0)
我get_string()
将被触发。
但是如果我打电话给记录器:
LOG_INFO("Value of x is: " << x);
出于某种原因,在 Visual Studio(2017 如果重要)中,当调用记录器的内部流成员(也是类型std::stringstream
)时,x
它会调用<ostream>
函数:_Myt& __CLR_OR_THIS_CALL operator<<(int _Val)
,即它将枚举视为整数,并将值打印为一个数字,而不是使用我的运算符重载。
但是,在 Linux 中 - 用 编译的相同代码gcc 5.4.0
调用 myoperator<<
并触发断言。
我真的不知道从哪里开始才能理解这一点......
所以真正的问题是 - 什么会导致编译器\操作系统之间存在这种差异?我从哪里开始调试它?或者如果有人知道是什么原因造成的,我很想知道。
编辑:
LOG_INFO
是最终调用的日志基础设施的宏:
m_logger->stream() << msg;
wherem_logger->stream()
返回std::stringstream&
并且msg
是模板化的值参数,在我的示例中是x