我有C ++ 98 API,它通过非const 引用获取值并更改此值。
具体来说,我使用的是OpenCV,函数为cv::rectangle()
,可以绘制cv::Mat &
图像。
此API也使用表达式模板来优化图像算法。我可以通过创建表示子图像的(非常量)临时包装对象在感兴趣区域(ROI)上绘制一个矩形。
使用VS2010,我可以写:
cv::Mat a(10,10,CV_8UC1); // create 10x10 image
Rect rec(0,0,2,2); // create 2x2 rectangle
cv::rectangle(a, rec, cv::Scalar::all(0)); // (1) draw 2x2 on full image
cv::rectangle(a(rec), rec, cv::Scalar::all(0)); // (2) draw 2x2 on 2x2 sub-image << !!!
这没有问题。在第(2)行,创建一个临时子图像包装器对象,并通过引用传递给cv::rectangle
。
但是,在带有C ++ 11支持的Clang 的XCode for iOS上,第(2)行会出现以下错误:
.../test.cpp:605:5: No matching function for call to 'rectangle'
.../core.hpp:2594:17: Candidate function not viable: expects an l-value for 1st argument
为了完整起见,这是相关的原型:
//! draws the rectangle outline or a solid rectangle covering rec in the image
CV_EXPORTS void rectangle(CV_IN_OUT Mat& img, Rect rec,
const Scalar& color, int thickness=1,
int lineType=8, int shift=0);
我认为这是因为a(rec)
创建了一个由ref cv::rectangle
传递的临时值,并且编译器不允许将此临时值转换为l值。也许这个临时自动定义为const?
我确实传递了一个临时的,但临时是一个实际的非const l值的包装器,应该允许自由更改。
有没有办法告诉Clang放松这些限制?
是否有可能告诉编译器这些头文件来自C ++ 98库,因此应该像C ++ 98一样处理临时文件?类似于做extern "C"
的事情?
有没有办法允许将临时值转换为l值。
当然,我可以编写auto b=a(rec)
并传递b
,但是这会用一堆命名的临时文件填充代码并击败包装类的目的。
答案 0 :(得分:5)
回答自己......经过一些研究后,似乎这种行为是由标准决定的,VS2010在这里是不符合的。
此行为旨在防止意外错误,但我的用例实际上是标准禁止的有效用例的示例。
规则:非const temporaries NOT 绑定到非 -const引用。
与 const temporaries的区别在于,您可以在临时文件上调用非const 方法。
如果这样的方法返回,例如*this
,然后 结果将成为 l-value ,因此将绑定到非const引用。< / p>
正如上面的@Xeo评论,在C ++ 11中,也可以将 r-value 的转换器写入 l-value :{{1} }。
但是,这应该特别小心使用(或根本不使用)。