在构造函数中传递 const 引用时如何强制编译器不接受右值
How to force the compiler not to accept rvalues when passing const reference in constructors
我在 VS2019 中有以下代码(尚未使用其他编译器进行测试)。
class A
{
// A should be a pure virtual class
};
class B
{
const A* member;
public:
B(const A& arg) : member{ &arg } {}
// Solves the problem
// B(const A&& arg) = delete;
void setA(const A& arg) { member = &arg; }
// Solves the problem
// setA(const A&& arg) = delete;
void setA(const A& arg) { member = &arg; }
};
int main()
{
B b(A{});
b.setA( A{} );
return 0;
}
现在,set 函数中的行为符合预期 - 它不接受右值。另一方面,构造函数在没有警告或编译器错误的情况下愉快地接受右值。正如我所看到的,编译器在构造函数的情况下假定复制语义,但在第二种情况下正确解析它。
如果我传递 A& 而不是 const A&
,则不会发生此行为
有没有办法强制编译器不接受构造函数中的右值?
解决该问题的一种方法是删除 B(const A&&) 构造函数。有没有更优雅的方式/统一的方式来做到这一点?使构造函数显式化仍然不能解决问题。
编辑 - 建议的 link 没有回答我的问题。正如我的问题中已经提到的解决方案(即明确删除 const 右值引用)。我在问除了显式删除重载是否还有另一种方法。我也试图了解它是否是一个错误(在编译器或标准中)或者它应该是这样。
如果是构造函数,删除不仅是最优雅的,而且是推荐的方法(五法则-零法则)。
b.setA( A{} );
将接受右值引用和一般引用。
B b(A{});
A a;
b.setA( a );
为避免这种情况,您必须使用删除重载版本:
void setA(const A&& arg) = delete;
我在 VS2019 中有以下代码(尚未使用其他编译器进行测试)。
class A
{
// A should be a pure virtual class
};
class B
{
const A* member;
public:
B(const A& arg) : member{ &arg } {}
// Solves the problem
// B(const A&& arg) = delete;
void setA(const A& arg) { member = &arg; }
// Solves the problem
// setA(const A&& arg) = delete;
void setA(const A& arg) { member = &arg; }
};
int main()
{
B b(A{});
b.setA( A{} );
return 0;
}
现在,set 函数中的行为符合预期 - 它不接受右值。另一方面,构造函数在没有警告或编译器错误的情况下愉快地接受右值。正如我所看到的,编译器在构造函数的情况下假定复制语义,但在第二种情况下正确解析它。 如果我传递 A& 而不是 const A&
,则不会发生此行为有没有办法强制编译器不接受构造函数中的右值? 解决该问题的一种方法是删除 B(const A&&) 构造函数。有没有更优雅的方式/统一的方式来做到这一点?使构造函数显式化仍然不能解决问题。
编辑 - 建议的 link 没有回答我的问题。正如我的问题中已经提到的解决方案(即明确删除 const 右值引用)。我在问除了显式删除重载是否还有另一种方法。我也试图了解它是否是一个错误(在编译器或标准中)或者它应该是这样。
如果是构造函数,删除不仅是最优雅的,而且是推荐的方法(五法则-零法则)。
b.setA( A{} );
将接受右值引用和一般引用。
B b(A{});
A a;
b.setA( a );
为避免这种情况,您必须使用删除重载版本:
void setA(const A&& arg) = delete;