-->

如何从原始类型变量通过右值引用函数参数复制时(How to copy from primitive

2019-09-30 08:17发布

我可以从非原始型变量由复制构造复制并使其通过右值引用函数的参数。

但如何能与原始类型变量做到这一点?

例如:

#include <cassert>
#include <iostream>
struct MyClass
{
   int m = 0;
};
MyClass& f(MyClass& x)
{
   x.m++;
   return x;
}
inline MyClass f(MyClass&& x)
{
   return f(x);
}
int& f(int& x)
{
   x++;
   return x;
}
inline int f(int&& x)
{
   return f(x);
}
int main()
{
   MyClass x1;
   auto y1 = f(MyClass(x1)); // Calls f(MyClass&&)
   // Result: x1.m = 0, y1.m = 1

   int x2 = 0;
   auto y2 = f(int(x2)); // Calls f(int&)
   // Result: x2 = 1, y2 = 1

   std::cout << x1.m << x2; // Result in VS2013: '01' But '00' in gcc and clang!
   assert(x1.m == x2); // FAILED in VS2013!!!
   return 0;
}

在Visual Studio 2013的结果是“01”与断言失败。

http://rextester.com/CAPY87169

Answer 1:

您的代码是正确的,这似乎是在VS2013中的错误。

简单MCVE:

#include <iostream>

void f(int& x)  { std::cout << "f(lv)\n"; }
void f(int&& x) { std::cout << "f(rv)\n"; }

int main()
{
   int x2 = 0;
   f( int(x2) );
   f( (int)x2 );
}

输出应该是:

f(rv)
f(rv)

MSVC在线测试仪

需要注意的是进一步的测试表明,该错误是真的(int)x2被视为由MSVC左值; 这不是与MSVC的扩展名错误,允许右值绑定到左值引用(因为右值引用是更好的匹配反正)。

您可以通过使用来解决这个问题/Za开关。


表达式int(x2)是由覆盖C ++ 14 [expr.type.conv] / 2(C ++ 11具有相同的编号):

后跟带括号表达式列表简单型说明符(7.1.6.2)类型名称说明符(14.6)构建体给出的表达式列表中指定的类型的值。 如果表达式列表是一个单一表达式,类型转换表达式是等效(在definedness,并且如果在含义定义)到相应的转换表达式(5.4)。

相应的铸造表达式为:

表达式(T)铸表达的结果是类型T的结果是左值如果T是一个左值引用类型或一个rvalue参考函数类型和如果T是一个rvalue参照到对象类型的x值; 否则结果是prvalue。



文章来源: How to copy from primitive type variables when passing through rvalue reference function arguments