使用一行代码m.s swap(std::stringstream());清除stringstream

c++ Clear stringstream using one-liner m.swap(std::stringstream());?

本文关键字:stringstream swap std 清除 代码 一行      更新时间:2023-10-16

我一直在使用以下代码清除std::stringstream:

m.swap(std::stringstream());

代码可能取自这个SO线程。最近,我在Visual Studio 2013中编译了我的代码,我收到了以下警告:

warning C4239: nonstandard extension used : 'argument' : conversion from 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>' to 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>> &'
1>          A non-const reference may only be bound to an lvalue

在使用/W4的早期版本的Visual Studio中,我没有收到任何警告。我记得在早期的版本中,我在清除stringstreams时遇到了麻烦,这就是为什么我一开始就使用了这段代码。

那么用这种方式清除stringstream是可移植的吗?如果不是,你能解释为什么不这样做吗?也有一个便携式的方式来清除字符串流?由于

编辑:这是所要求的代码。使用/W4编译它以查看警告。
int _tmain(int argc, _TCHAR* argv[])
{
    std::stringstream m;
    m.swap(std::stringstream());
    return 0;
}

std::stringstream::swap()的签名:

void swap( basic_stringstream& other );

可以看到,swap()对其参数采用左值引用。正如编译器正确告诉您的那样,右值或临时值不能绑定到左值引用。有些编译器支持允许您这样做的非标准扩展,但我建议您保持在标准的范围内,这样更安全。

然而,虽然您可能无法将临时值绑定到左值引用,但您可以使用以下std::skipws技巧临时值转换为左值:
m.swap(static_cast<std::stringstream&>(stringstream{} >> std::skipws));

或者

std::stringstream{}.swap(m):

在第一个示例中,函数operator>>()返回对流的引用,该引用与swap()一起使用是安全的,因为保存实参的引用在函数结束时被销毁。

std::swap函数接受两个非const形参进行交换。这是因为在调用函数时这两个参数都改变了。类似地,std::stringstream::swap(...)函数接受一个非const形参进行交换。例如:

std::vector<int> vec1, vec2;
std::swap(vec1, vec2);

在上面的示例中,vec1vec2都被改变了。当您尝试这样做时…

m.swap(std::stringstream());

…您试图将临时std::stringstream()的内容与m的内容赋值,即使您的意图只是清除m的内容,对于编译器来说,这看起来像是一个错误。

要消除警告,只需在执行交换之前声明一个临时std::stringstream。这样的:

std::stringstream temp;
m.swap(temp);

标准不允许使用swap。声明为

template <typename CharT, typename Traits, typename Allocator>
void std::basic_stringstream<CharT, Traits, Allocator>::swap(
    basic_stringstream& other);

意味着两个stringstream对象都将被修改。但是表达式std::stringstream()是一个右值(特别是一个临时值),并且c++不允许将非const左值引用绑定到临时值,因为修改临时值通常不是真正的目的。

简单的解决方案是:

m = std::stringstream();

但是如果你需要在不支持c++ 11的情况下支持编译器,这两种方法都行不通,因为在c++ 03标准中,stringstream没有swap函数,也没有公共的operator=。在这种情况下,您需要使用:

m.clear();
m.str(std::string());