首先,这个问题是不是重复的功能双到std ::移动?或者std :: move的反转是否存在?.我不是要问一种机制,以防止在原本会发生的情况下移动,而是复制; 相反,我正在询问一种机制,使rvalue被接受在一个将被绑定到可修改左值引用的位置.事实上,这std::move与发明的情况完全相反(即,在一个将被绑定到(可修改的)右值参考的位置上接受可修改的左值).
在我感兴趣的情况下,不会接受右值,因为上下文需要可修改的左值引用.由于某种原因,我不太明白但愿意接受,(可修改的)右值表达式将绑定到一个常量左值引用(不引入额外的临时值),但它不会绑定到可修改的左值引用( gcc给我的错误信息是"从'A'类型的右值'中'A&'类型的非const引用的无效初始化",而clang说"对类型'A'的非const左值引用不能绑定到临时的输入'A'';奇怪的是我无法让这些编译器中的任何一个承认有问题的表达式有'A &&'类型,即使该表达式实际上是static_cast<A&&>(...)单独引发错误的形式.我可以理解,通常不希望在需要可修改的左值引用的位置接受rvalue表达式,因为它意味着通过该左值引用完成的任何修改都将丢失,但正如调用std::move对编译器说的那样"我知道这是一个左值,它将被绑定到右值参考(参数),因此可能会被盗,但我知道我在做什么,这里没关系"我想在我的案例中说"我知道这是临时的,它将被绑定到一个可修改的左值引用(参数),因此通过左值引用所做的任何更改都会被忽略,但我知道我在做什么,这里没关系".
我可以通过从rvalue 初始化类型A 的命名对象,然后提供需要可修改左值引用的名称来解决问题.我不认为这有额外的运行时开销(无论如何都需要rvalue的临时开启),但是必须这样做在几个方面很尴尬:必须引入一个虚拟名称,可能只需引入一个复合语句保持声明,将产生rvalue的表达式与函数调用分开,它为其提供参数.我的问题是否可以在不引入虚拟名称的情况下完成:
- 是否有任何方法(例如使用强制转换)将类型A的rvalue表达式绑定到类型A的可修改左值引用并且不引入类型A的命名对象?
- 如果没有,这是一个刻意的选择吗?(如果是这样,为什么?)如果有,是否有类似于
std::move标准提供的机制来促进它?
这是一个简化的插图,我需要这样的转换.我故意删除了A的特殊构造函数,以确保错误消息不涉及编译器决定引入的临时文件.当A&被替换时,所有错误都会消失const A&.
class A
{ int n;
public:
A(int n) : n(n) {}
A(const A&) = delete; // no copying
A(const A&&) = delete; // no moving either
int value() const { return n; }
};
int f(A& x) { return x.value(); }
void g()
{ A& aref0 = A(4); // error
// exact same error with "= static_cast<A&&>(A(4))" instead of A(4)
A& aref1 = static_cast<A&>(A(5)); // error
// exact same error with "= static_cast<A&&>(A(5))" instead of A(5)
f (A(6)); //error
// exact same error with "= static_cast<A&&>(A(6))" instead of A(6)
A a(7);
f(a); // this works
A& aref2 = a; // this works too, of course
}
Run Code Online (Sandbox Code Playgroud)
对于那些想知道我为什么需要这个的人,这里有一个用例.我有一个f带有参数的函数作为输入参数,有时也作为输出参数,用"更专业"的值替换提供的值(值表示树结构,并且可能已经填充了一些缺少的分支); 因此,该值作为可修改的左值引用传递.我还有一些全局变量保存有时用于为此参数提供值的值; 这些值是不可改变的,因为它们已经完全专业化了.尽管有这种恒定的性质,我过去常常不会声明这些变量const,因为这会使它们不适合作为参数.但它们实际上被认为是全局和永久常量,因此我想重写我的代码以使其明确,并且还避免在更改实现时意外发生错误的可能性f(例如,它可能决定从其中移动)抛出异常时的参数;当参数表示将被异常销毁的局部变量时,这将是正常的,但如果它被绑定到全局"常量"则会是灾难性的.因此,我决定在传递其中一个全局常量时复制f.有一个函数copy可以生成并返回这样的副本,我想把它作为参数调用f; 唉copy(c)作为一个右值这不能为理由来进行上面解释的,尽管这种用法是绝对安全的,而实际上比我以前的解决方案更加安全.
下面提供的功能是个坏主意.不要使用它.它为悬挂参考提供了一条非常简单的途径.我认为需要它的代码有问题并采取相应的行动.
尽管如此,由于某种原因,我认为这是一项有趣的练习,所以我不得不表现出来.
在函数内部,其参数的名称是左值,即使参数是右值引用.您可以使用该属性将参数作为左值引用返回.
template <typename T>
constexpr T& as_lvalue(T&& t) {
return t;
};
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案就是:
template<typename T>
T& force(T&& t){
return t;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
780 次 |
| 最近记录: |