其实,这是一个非常好的问题。到目前为止,我还一直在使用通用参考技巧加上enable_if
锤子。在这里,我提出了一个不使用模板并使用左值转换作为替代方案的解决方案。
下面是其中的情况出现使用就地ofstream
使用已知的例子是不可能的(或很难)在C++ 98的真实例子(我用ostringstream
在这个例子中,以使其更清晰)。
首先,您将在C++ 98中看到一个关于左值引用的函数。
#include<iostream>
#include<sstream>
struct A{int impl_;};
std::ostringstream& operator<<(std::ostringstream& oss, A const& a){
oss << "A(" << a.impl_ << ")"; // possibly much longer code.
return oss;
}
// naive C++11 rvalue overload without using templates
std::ostringstream& operator<<(std::ostringstream&& oss, A const& a){
oss << "A(" << a.impl_ << ")"; // ok, but there is code repetition.
return oss;
}
int main() {
A a{2};
{// C++98 way
std::ostringstream oss;
oss << a;
std::cout << oss.str() << std::endl; // prints "A(2)", ok"
}
{// possible with C++11, because of the rvalue overload
std::cout << (std::ostringstream() << a).str() << std::endl; //prints "A(2)", ok
}
}
正如您在C++ 11中看到的,我们可以实现我们在C++ 98中无法实现的功能。那就是利用ostringstream
(或ofstream
)就地。现在出现OP问题,两个重载看起来非常相似,都可以加入一个?
一种选择是使用通用参考(Ostream&&
),并且可选地使用enable_if
来限制类型。不是很优雅。
我发现通过使用这个“真实世界”的例子是,如果想要使用相同的代码左值参考和右值ref是因为可能你可以将一个转换为另一个!
std::ostringstream& operator<<(std::ostringstream&& oss, A const& a){
return operator<<(oss, a);
}
这看起来像一个无限递归函数,但它不是因为oss
是一个左值引用(是的,它是一个左值引用,因为它有一个名字)。所以它会调用其他的超载。
您仍然需要编写两个函数,但其中一个代码不需要维护。总之,如果“有意义”将函数同时应用于(非常量)左值引用和右值,这也意味着您可以将右值转换为左值并因此转发给单个函数。请注意,“它有意义”取决于上下文和预期代码的含义,而且我们必须通过明确地调用左值过载来“告知”编译器。
我并不是说这比使用通用参考更好,我认为它是一种替代方法,可以证明其意图更加清晰。
可编辑代码:http://ideone.com/XSxsvY。 (欢迎反馈)
rvalue传递简单类型如'int'没有意义。在更一般的情况下,我相信C++ 11有一个特殊情况,其中右值参数将被读作右值或左值参数。尽管如此,我不记得确切的情况。 – Dave 2013-05-04 16:38:40
所以你希望'x'是一个右值引用(如果通过右值引用)或左值引用给'const'?我是否正确理解,X &&不会被你接受,因为当左值被传递时,它将是对非''constst'的左值引用? – 2013-05-04 16:41:22
嗯,我们走吧,我相信你正在努力做到这一点:http://thbecker.net/articles/rvalue_references/section_07.html这是在下一页使用rvalues解释。如果我误解了这个问题,大叫大叫。 – Dave 2013-05-04 16:41:40