§27.7.3.9为以下内容定义以下重载operator<<:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
Run Code Online (Sandbox Code Playgroud)
效果:
os << x
退货:os
(§27.7.2.6定义rvalue重载operator>>.)
基本上,它只是转发到左值超载.我认为这个重载非常危险(实际上istream比ostream实际更重要),请考虑以下内容:
#include <sstream>
#include <iostream>
int main(){
auto& s = (std::stringstream() << "hi there!\n");
std::cout << s.rdbuf(); // oops
}
Run Code Online (Sandbox Code Playgroud)
关于Ideone的实例(未定义行为的完美示例.在MSVC10上没有为我打印).
上面的例子看起来做作,但它不应该太难进入这个情况在通用代码或传递时(std::stringstream() << "text"),以提供一个左值和一个右值过载和存储功能std::ostream或std::istream以不同的方式根据过载.
现在,又将返回a basic_ostream<charT, traits>&&并指定以下内容的参数是什么?
返回: move(os)
(同样的basic_istream.)
有什么我可以忽略的吗?在目前的状态,在我看来,它看起来很危险,就像一个缺陷.我浏览了LWG问题列表并找到了这个提议(嗨@HowardHinnant!).它确实会返回一个右值,但是只为能够链这个特殊的运营商,而不是专门针对我上面描述的安全问题(尽管它肯定是额外的好处,确实 …
关于模板化函数中的完美转发的广泛讨论,允许有效地将左值或右值参数作为参数传递给其他函数.
但是,我无法找到关于完美回归或等效完美传递的讨论.(相关问题完美传递并未完全解决此问题.)
考虑修改范围的函数的情况,并应返回修改的范围.我们需要两个单独的函数来有效地解决左值和右值参数的情况:
// Given a reference to an lvalue range, return a reference to the same modified range.
// (There is no allocation or move.)
template<typename T> T& sortr(T& r) {
std::sort(std::begin(r),std::end(r));
return r;
}
// Given an rvalue range, return the same range via (hopefully) a move construction.
template<typename T> T sortr(T&& r) {
std::sort(std::begin(r),std::end(r));
return std::move(r);
}
Run Code Online (Sandbox Code Playgroud)
当然,包括这两个定义会导致歧义错误,因为第二个定义也与左值引用匹配.
一个激励性的例子(和测试用途)如下:
#include <iostream>
#include <vector>
#include <algorithm>
std::ostream& operator<<(std::ostream& os, const std::vector<int>& v) …Run Code Online (Sandbox Code Playgroud)