C++ c++;使用一个线性m.swap(std::stringstream())清除stringstream;?

C++ c++;使用一个线性m.swap(std::stringstream())清除stringstream;?,c++,visual-studio-2013,stringstream,C++,Visual Studio 2013,Stringstream,我一直在使用以下代码清除std::stringstream: m.swap(std::stringstream()); 代码可能取自。最近,我在Visual Studio 2013中编译了代码,收到了以下警告: warning C4239: nonstandard extension used : 'argument' : conversion from 'std::basic_stringstream<char,std::char_traits<char>,std::all

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

m.swap(std::stringstream());
代码可能取自。最近,我在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

std::swap
函数使用两个非常量参数进行交换。这是因为调用函数时两个参数都会更改。类似地,
std::stringstream::swap(…)
函数使用一个非常量参数进行交换

例如:

std::vector<int> vec1, vec2;
std::swap(vec1, vec2);
。。。您试图用
m
的内容分配临时
std::stringstream()
的内容,这对编译器来说就像一个bug,即使您的目的只是清除
m
的内容

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

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

这是std::stringstream::swap()的签名。:

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

但是,虽然您可能无法将临时值绑定到左值引用,但可以使用以下
std::skipws
技巧将临时值转换为左值:

m.swap(static_cast<std::stringstream&>(stringstream{} >> std::skipws));

在第一个示例中,函数
操作符>>()
返回对流的引用,可以安全地与
交换()
一起使用,因为保存参数的引用在函数末尾被销毁。

标准不允许使用
交换。声明是

template <typename CharT, typename Traits, typename Allocator>
void std::basic_stringstream<CharT, Traits, Allocator>::swap(
    basic_stringstream& other);
但是如果您需要支持不支持C++11的编译器,这两种编译器都不起作用,因为在C++03标准中,
stringstream
没有
swap
函数,也没有公共
操作符=
。在这种情况下,您需要:

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

我无法复制它,老兄,你能发布一些代码吗?@Manu343726 relax dude。在我的VS++2013中,它编译得很好。@Manu343726因为没有其他编译器有非标准的扩展。哦,等等,他们都有。(不可否认,这个特定的扩展确实很糟糕)我在VS2013中做了一个控制台应用程序,我运行了您发布的代码,没有任何优化,我无法复制。它编译得很好,没有警告。或者,先创建临时文件<代码>标准::stringstream().swap(m)
@BillyONeal-确实你也可以这么做!有点类似的问题。。。请参阅关于
左值
模板的注释。基本上,您将临时值绑定到非常量左值引用,这是不可能的。您必须使用C++11中的移动语义从_temp(T&&x){return x;}创建对临时模板T&ref_的引用,然后替换
m.swap(stringstream())通过
m.swap(ref_from_temp(stringstream()))@vsoftco谢谢你的建议。我决定使用Billy的一行程序,因为尽管它与Visual Studio 2010不完全兼容,但它可以与Visual Studio 2010兼容。您如何解释发布的示例编译的事实?使用.str()的问题显然是清除流并不总是对我有效,我不记得为什么。
m.clear()
可能还需要执行完全重置。也许还有其他事情。仅使用C++03函数是很困难的。好的,谢谢你提供的额外信息,我很感激。我决定使用
std::stringstream().swap(m)因为即使不是C++03,它也可以在VisualStudio2010和2013中工作。我真的希望更好的可移植性,但如果需要的不是clear()和str(std::string()),我不想冒引入bug的风险。谢谢你的回答和想法。@vsoftco它到底是如何工作的?你收到错误了吗?如果是,那是什么?是的,
错误:对类型“std::u 1::basic_stringstream”的非常量左值引用无法绑定到不相关类型“std::u 1::basic_istream”的值。
这是代码
#include#include使用命名空间std;int main(){stringstream m;m.swap(stringstream{}>>skipws);}
如果您使用move函数添加引用,它会起作用,正如您在前面谈到我的stringstreams问题时提到的那样。
m.swap(static_cast<std::stringstream&>(stringstream{} >> std::skipws));
std::stringstream{}.swap(m):
template <typename CharT, typename Traits, typename Allocator>
void std::basic_stringstream<CharT, Traits, Allocator>::swap(
    basic_stringstream& other);
m = std::stringstream();
m.clear();
m.str(std::string());