如何允许将C++ 98 API的临时值转换为l值

Adi*_*vit 3 opencv clang lvalue ios c++11

我有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 << !!!
Run Code Online (Sandbox Code Playgroud)

这没有问题.在第(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 
Run Code Online (Sandbox Code Playgroud)

为了完整起见,这是相关的原型:

//! 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);
Run Code Online (Sandbox Code Playgroud)

我认为这是因为a(rec)创建了一个由ref传递的临时文件,cv::rectangle并且编译器不允许将此临时文件转换为l值.也许这个临时自动定义为const?
我确实传递了一个临时的,但临时是一个实际非const l值的包装器,应该允许自由更改.

有没有办法告诉Clang放松这些限制?
是否有可能告诉编译器这些头文件来自C++ 98库,因此应该处理像C++ 98中的临时文件?类似于做什么extern "C"
有没有办法允许将临时值转换为l值.

当然,我可以编写auto b=a(rec)并传递b,但是用一堆命名的临时文件填充代码并击败包装类的目的.

Adi*_*vit 5

回答自己...经过一些研究后,似乎这种行为是由标准决定的,VS2010在这里是不符合要求的.
此行为旨在防止意外错误,但我的用例实际上是标准禁止的有效用例的示例.

规则:非const临时值绑定到 const引用.
const临时的区别在于,你可以在临时上调用非const方法.
如果这样的方法返回,例如*this,那么结果l值并且因此将绑定到非const引用.

有关详细信息,请参阅此处此处.

正如上面的@Xeo评论,在C++ 11中,也可以将转换器从r值写入l值:template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon.
但是,应该特别小心使用(或根本不使用).