下面的代码演示了在将返回值从std::stringstream::operator<<
流式传输到std::ostream
示例(如std::cout
)时,显式static_cast
(从std::basic_ostream<char>
返回到std::stringstream
)对于 * g ++9.4.0 * 是必需的,并且会导致编译错误 * g ++1.3 *:
// main.cpp
#include <iostream>
#include <sstream>
#define LOG(x) \
std::cout << (static_cast<std::stringstream&>(std::stringstream{} << x).str()) << std::endl;
//std::cout << ((std::stringstream{} << x).str()) << std::endl;
int main(int argc, char* argv[]) {
LOG("hello, world!");
return 0;
}
$ g++ --version && g++ ./main.cpp && ./a.out
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
hello, world!
$
$ g++ --version && g++ -g ./main.cpp && ./a.out
g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
./main.cpp: In function ‘int main(int, char**)’:
./main.cpp:7:15: error: invalid ‘static_cast’ from type ‘std::__cxx11::basic_stringstream<char>’ to type ‘std::stringstream&’ {aka ‘std::__cxx11::basic_stringstream<char>&’}
7 | std::cout << (static_cast<std::stringstream&>(std::stringstream{} << x).str()) << std::endl;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./main.cpp:11:3: note: in expansion of macro ‘LOG’
11 | LOG("hello, world!");
| ^~~
$
反之亦然:缺少显式static_cast
会导致g++ 9.4.0
发出错误,并成功执行g++ 11.3
:
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
这是一个麻烦的来源,因为我需要在两个环境中编译这段代码:一个具有g++ 9.4.0
,另一个具有g++ 11.3
。
- 请帮助我了解这些编译错误的性质,特别是 * g ++9.4.0 * 和 * g ++11.3 * 之间的差异:**
- 哪个编译器版本是正确的?
- 是否有一个预处理器宏来测试编译器版本,通过它我可以条件化
LOG(x)
的定义?
(我会假定 * g ++11.3 * 是正确的,因为它是最近的;但这让我很疑惑为什么 * 不 * 显式static_cast
是必要的?根据https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt,std::stringstream
插入操作符确实返回了对基类basic_ostream
的引用,而基类没有str()
函数,所以我很困惑为什么std::cout << ((std::stringstream{} << x).str()) << std::endl;
是有效的)
1条答案
按热度按时间3hvapo4f1#
试试看
因为(std::stringstream{}〈〈x)不是一个左值。
实际上,clang++给予了一个更好的错误消息:
流延CPP:9:2:错误:对类型“basic_stringstream”的非常数左值引用<...>无法绑定到类型“basic_stringstream”的临时值<...>