显式删除const &&
重载
临时对象可以通过将其绑定到左值引用(在函数调用中)来延长其生命周期const
,但它不能绑定到非const
左值引用。这意味着您的原始示例实现了所寻求的行为(不能使用临时对象调用),但代价是使参数非const
-(即使实现只查询并且不改变对象)。可以说,这违反const
了正确性。
当您的自由函数 API 正在检查一个Object
对象时,您可以考虑将其更改为成员函数并使用 ref-qualifiers 显式删除将由重载决议为临时对象选择的重载。第一种方法可能是简单地删除&&
重载:
struct Object {
// ...
void foo() const & {}
void foo() && = delete;
};
int main() {
Object o = Object();
const Object co = Object();
o.foo();
co.foo();
//Object().foo(); // error: use of deleted function
}
但是,这并不禁止const 临时对象的情况(尽管有些人为)以及可从 const 对象(const xvalues)移动,因为已删除的非右值引用限定符重载对于右值参数const
是不可行的:const
std::move(co).foo(); // Accepted.
static_cast<const Object&&>(Object()).foo(); // Accepted.
因此,除了显式删除&&
重载,我们还可以通过显式删除const &&
重载来删除极端情况,因为这也是非const
临时对象的重载选择:
struct Object {
// ...
void foo() const & {}
void foo() const && = delete;
};
int main() {
Object o = Object();
const Object co = Object();
o.foo();
co.foo();
//std::move(o).foo(); // error: use of deleted function
//std::move(co).foo(); // error: use of deleted function
//Object().foo(); // error: use of deleted function
//static_cast<const volatile Object&&>(Object()).foo(); // error: use of deleted function
}
我们可能会注意到,同样的方法也被用于 ; 的std::ref
和std::cref
辅助函数std::reference_wrapper
。来自[functional.sym]:
// [refwrap], reference_wrapper
// ...
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
// ...
因为您自然想删除临时对象的引用包装器。