我正在添加新的运算符重载以利用c ++ 0x rvalue引用,我觉得我正在生成大量冗余代码.
我有一个类,tree它在双值上包含一个代数运算树.这是一个示例用例:
tree x = 1.23;
tree y = 8.19;
tree z = (x + y)/67.31 - 3.15*y;
...
std::cout << z; // prints "(1.23 + 8.19)/67.31 - 3.15*8.19"
Run Code Online (Sandbox Code Playgroud)
对于每个二元运算(如加号),每一方可以是左值tree,右值tree或double.这导致每个二进制操作有8个重载:
// core rvalue overloads for plus:
tree operator +(const tree& a, const tree& b);
tree operator +(const tree& a, tree&& b);
tree operator +(tree&& a, const tree& b);
tree operator +(tree&& a, tree&& b);
// cast and forward cases: …Run Code Online (Sandbox Code Playgroud) (我在comp.std.c ++上询问了这个问题的变体,但没有得到答案.)
为什么f(arg)在这段代码中的调用调用const ref重载f?
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
Run Code Online (Sandbox Code Playgroud)
我的直觉说f(string &&)应该选择重载,因为arg无论如何都需要转换为临时值,并且临时匹配rvalue引用比lvalue引用更好.
这不是GCC和 MSVC中发生的事情(编辑:谢谢Sumant:它不会发生在GCC 4.3-4.5中).至少在G ++和 MSVC中,任何左值都不会绑定到右值引用参数,即使创建了一个中间临时值.实际上,如果不存在const ref重载,编译器会诊断出错误.然而,编写f(arg + 0) 或f(std::string(arg)) 不选择右值引用过载如你所愿.
从我对C++ 0x标准的阅读中,似乎在考虑是否f(string &&)可行时应考虑将const char*隐式转换为字符串,就像传递const lvalue ref参数时一样.第13.3节(重载解析)在很多地方没有区分rvalue refs和const引用.此外,似乎阻止左值绑定到右值引用(13.3.3.1.4/3)的规则不适用,如果存在中间临时值 - 毕竟,从临时值移动是完全安全的.
这是:
编辑:我有一个相关的后续问题:C++ 0x rvalue引用 - lvalues-rvalue绑定
我有三个函数调用,我认为应该对它们进行相同的处理,但显然它们不是.我试图理解为什么三个中的一个不编译(g ++ -std = c ++ 0x).
// Minimal example to reproduce a compile bug I want to understand.
#include <iostream>
#include <string>
using namespace std;
void bar(const string &&x) { cout << "bar: " << x << endl; }
string returns_a_string() { return string("cow"); }
int main( int argc, char *argv[] )
{
bar(string("horse")); // ok
bar(returns_a_string()); // ok
string aardvark = "aardvark";
bar(aardvark); // not ok, fails to compile, error in next comment
/*
rvalue-min.cpp:29:22: error: cannot bind …Run Code Online (Sandbox Code Playgroud)