简体   繁体   English

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

[英]How to allow conversion of temporary to l-value for C++98 API

I have C++98 API that takes a value by non-const reference and changes this value. 我有C ++ 98 API,通过非const 引用获取值并更改此值。
Specifically, I'm using OpenCV and the function is cv::rectangle() which takes a cv::Mat & image to be drawn upon. 具体来说,我正在使用OpenCV,函数是cv::rectangle() ,它采用了cv::Mat & image。

This same API also uses expression templates to optimize image arithmetic. 同样的API也使用表达式模板来优化图像算术。 I can draw a rectangle on a Region-of-Interest (ROI) by creating a (non-const) temporary wrapper object that represents a sub-image. 我可以通过创建表示子图像的(非常量)临时包装对象在感兴趣区域(ROI)上绘制一个矩形。

With VS2010, I can write: 有了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 << !!!

This works without a problem. 这没有问题。 On line (2) a temporary sub-image wrapper object is created and passed to cv::rectangle by reference. 在第(2)行,创建一个临时子图像包装器对象,并通过引用传递给cv::rectangle

However, on XCode for iOS with Clang with C++11 support , line (2) give the following error: 但是,在支持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 

For completeness, here's the relevant prototype: 为了完整起见,这是相关的原型:

//! 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);

I think this happens because a(rec) creates a temporary that is being passed by ref to cv::rectangle and the compiler does not allow this temporary to be converted to an l-value. 我认为这是因为a(rec)创建了一个临时的,它被ref传递给cv::rectangle ,并且编译器不允许将此临时转换为l值。 Perhaps this temporary is automatically defined as const? 也许这个临时自动定义为const?
I am indeed passing a temporary, but the temporary is a wrapper for an actual non-const l-value and should be allowed to change freely. 我确实传递了一个临时的,但临时是一个实际的非const l值的包装器,应该允许自由更改。

Is there a way to tell Clang to relax these constraints? 有没有办法告诉Clang放松这些限制?
Is it somehow possible to tell the compiler that these headers are coming from a C++98 library and thus should handle temporaries like in C++98? 是否有可能告诉编译器这些头文件来自C ++ 98库,因此应该像C ++ 98一样处理临时文件? Something akin to doing extern "C" ? 类似于做extern "C"
Is there a way to allow conversion of the temporary to an l-value. 有没有办法允许将临时值转换为l值。

Of course, I can write auto b=a(rec) and pass b instead, but that fills up the code with a bunch of named temporaries and beats the purpose of the wrapper classes. 当然,我可以编写auto b=a(rec)并传递b代替,但是用一堆命名的临时代码填充代码并击败包装类的目的。

Answering myself... after some more research it seems that this behavior is dictated by the standard, and VS2010 is non-conformant here. 回答自己...经过一些研究后,似乎这种行为是由标准决定的,VS2010在这里是不符合要求的。
This behavior was designed to prevent accidental errors, though my use-case is actually an example for a valid use-case that is forbidden by the standard. 此行为旨在防止意外错误,但我的用例实际上是标准禁止的有效用例的示例。

The rule: non-const temporaries do NOT bind to non -const references. 规则: 非const临时值绑定到 const引用。
The difference from const temporaries, is that you can call non-const methods on the temporary. const临时的区别在于,你可以在临时上调用非const方法。
If such a method returns, eg *this , then that result will be an l-value and will, thus, bind to the non-const reference. 如果这样的方法返回,例如*this ,则结果l值 ,因此将绑定到非const引用。

For more info see here and here . 有关详细信息,请参阅此处此处

As @Xeo comments above, in C++11 it's also possible to write a converter from an r-value to an l-value : template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon 正如上面的@Xeo评论,在C ++ 11中,也可以编写从r值l值的转换器: template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon . template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon
However, this should be used with extra care (or not at all). 但是,应该特别小心使用(或根本不使用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM