微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 GCC 中对 wstringstream 类型的参数使用流插入而不是 MSVC 时出错

如何解决在 GCC 中对 wstringstream 类型的参数使用流插入而不是 MSVC 时出错

我有一个标题,用于帮助使用 MSVC v141 (Visual Studio 2017) 登录应用程序。由于这些日志实用程序很有用,因此我想将其带入我刚刚开始的使用 CMake 和 MinGW/GCC 的项目中。标头本身应该是独立的,它只是执行一些魔术来抽象出公共信息和流目的地,这样我所要做的就是在主循环中调用 InitLogging() 然后调用 LogInfo/LogError/etc,但是当我编译时针对 MinGW(10.3.0 [MSYS2])/GCC(7.5.0 [Ubuntu]),我收到以下错误

error: invalid initialization of reference of type ‘const wstringstream& {aka const std::__cxx11::basic_stringstream<wchar_t>&}’ from expression of type ‘std::basic_ostream<wchar_t>’
 #define LogInfo(str) { LogMessage(eLogLevel_INFO,std::wstringstream() << LOG_HELPER << str,std::wstringstream() << LOG_HELPER_2);  }
/mnt/d/dev/test_logger/src/main.cpp:9:2: note: in expansion of macro ‘LogInfo’
  LogInfo(L"Test log");

这是标题中的相关代码

std::wstring Time2String();

#define LOG_HELPER __FUNCTION__ << L"(): "
#define LOG_HELPER_2 L"[" << Time2String() << "] "

inline void LogMessage(eLogLevel lvl,const std::wstringstream& str,const std::wstringstream& logHelper);//Snipped deFinition

#define LogInfo(str) { LogMessage(eLogLevel_INFO,std::wstringstream() << LOG_HELPER_2);  }

如果我只是简单地传递 std::wstreamstring() 而不进行任何插入,或者如果我在调用之外实例化该类型的变量并在调用之外对这些变量执行插入,那么编译器很高兴,尽管它同样如果我尝试对来自类似于当前 #define函数调用的变量执行插入,我会很不高兴。

示例:

LogInfo(L"Test log");//compile error

/*******************************************/
std::wstringstream tmpsstream,tmpsstream2;
tmpsstream << LOG_HELPER << L"Test log";
tmpsstream2 << LOG_HELPER_2;
LogMessage(eLogLevel_INFO,tmpsstream,tmpsstream2);//no error

/*******************************************/
LogMessage(eLogLevel_INFO,std::wstringstream(),std::wstringstream());//no error

/*******************************************/
std::wstringstream tmpsstream,tmpsstream2;
LogMessage(eLogLevel_INFO,tmpsstream << LOG_HELPER << L"Test log",tmpsstream2 << LOG_HELPER_2);//compile error

这是 GCC 中的错误还是 MSVC 做了不该做的事情?

解决方法

operator<< 返回对其调用的 std::basic_ostream 对象的引用,即(在本例中)它返回 std::wostream&,而不是您期望的 std::wstringstream&。您无法从 const std::wstringstring& 初始化 std::wostream&,因此会出现错误消息。

由于您的 LogInfo() 宏正在创建一个带有 {} 大括号的新范围,您可以利用您已经发现的解决方案:

如果我......在调用之外实例化该类型的变量并在调用之外对这些变量执行插入,那么编译器很高兴

试试这个:

#define LogInfo(str) { \
    std::wstringstream wss,wss2; \
    wss << LOG_HELPER << str; \
    wss2 << LOG_HELPER_2; \
    LogMessage(eLogLevel_INFO,wss,wss2); \
}

Online Demo

否则,如果您不想使用局部变量,那么您将需要显式类型转换 std::wostream& 返回的最终 operator<< 引用,例如:

#define LogInfo(str) { \
    LogMessage(eLogLevel_INFO,\
        static_cast<std::wstringstream&>(std::wstringstream() << LOG_HELPER << str),\
        static_cast<std::wstringstream&>(std::wstringstream() << LOG_HELPER_2) \
    ); \
}

Online Demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。