为什么 ref-qualifier 和 cv-qualifier 在运算符重载上允许右值赋值?
Why do ref-qualifier together with cv-qualifier on operator overloading allow rvalue assignment?
向运算符添加引用限定符将消除进行右值赋值的可能性
例如用g++ -std=c++14 bar.cpp && ./a.out
编译如下
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
};
int main()
{
foo() += 10;
}
会给你
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: passing ‘foo’ as ‘this’ argument discards qualifiers [-fpermissive]
14 | foo() += 10;
| ^~
bar.cpp:6:10: note: in call to ‘void foo::operator+=(int) &’
6 | void operator+=(int x) & { printf("%d\n", x+2); }
| ^~~~~~~~
您当然可以通过添加明确的 &&
来“解决”这个问题
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) && { printf("%d\n", x+3); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
13
但是添加 const &
也可以让您在结构实例上调用 +=
。
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
14
要“修复”此问题,必须明确删除 const &&
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
void operator+=(int x) const && = delete;
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: use of deleted function ‘void foo::operator+=(int) const &&’
14 | foo() += 10;
| ^~
bar.cpp:9:10: note: declared here
9 | void operator+=(int x) const && = delete;
| ^~~~~~~~
这是为什么?为什么添加 ref 限定符会隐式删除右值赋值?但是添加 cv-qualifier 和 ref-qualifier 似乎隐含地添加了右值赋值?
我确定我在这里遗漏了一些明显的东西。但是Google-Wan Kenobi好像不能帮我理解。
因为右值可以绑定到 const
的左值引用。就像下面的代码一样:
foo& r1 = foo(); // invalid; rvalues can't be bound to lvalue-reference to non-const
const foo& r2 = foo(); // fine; rvalues can be bound to lvalue-reference to const
顺便说一句:在调用右值时,用右值引用限定的重载在重载决议中获胜。这就是为什么您将其标记为 delete
明确按预期工作。
向运算符添加引用限定符将消除进行右值赋值的可能性
例如用g++ -std=c++14 bar.cpp && ./a.out
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
};
int main()
{
foo() += 10;
}
会给你
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: passing ‘foo’ as ‘this’ argument discards qualifiers [-fpermissive]
14 | foo() += 10;
| ^~
bar.cpp:6:10: note: in call to ‘void foo::operator+=(int) &’
6 | void operator+=(int x) & { printf("%d\n", x+2); }
| ^~~~~~~~
您当然可以通过添加明确的 &&
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) && { printf("%d\n", x+3); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
13
但是添加 const &
也可以让您在结构实例上调用 +=
。
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
14
要“修复”此问题,必须明确删除 const &&
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
void operator+=(int x) const && = delete;
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: use of deleted function ‘void foo::operator+=(int) const &&’
14 | foo() += 10;
| ^~
bar.cpp:9:10: note: declared here
9 | void operator+=(int x) const && = delete;
| ^~~~~~~~
这是为什么?为什么添加 ref 限定符会隐式删除右值赋值?但是添加 cv-qualifier 和 ref-qualifier 似乎隐含地添加了右值赋值?
我确定我在这里遗漏了一些明显的东西。但是Google-Wan Kenobi好像不能帮我理解。
因为右值可以绑定到 const
的左值引用。就像下面的代码一样:
foo& r1 = foo(); // invalid; rvalues can't be bound to lvalue-reference to non-const
const foo& r2 = foo(); // fine; rvalues can be bound to lvalue-reference to const
顺便说一句:在调用右值时,用右值引用限定的重载在重载决议中获胜。这就是为什么您将其标记为 delete
明确按预期工作。