Как разрешить преобразование временного значения в l-значение для C++98 API


У меня есть C++98 API, который принимает значение по не-const ссылке и изменяет это значение.
В частности, я использую OpenCV, и функция cv::rectangle(), которая принимает изображение cv::Mat & для рисования.

Этот же API также использует шаблоны выражений для оптимизации арифметики изображений. Я могу нарисовать прямоугольник на интересующей области (ROI), создав временный объект-оболочку (non-const), представляющий подобраз.

С 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 по ссылке.

Однако в XCode для iOS с Clang с поддержкой C++11, строка (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) создает временный файл, который передается по ссылке в cv::rectangle, и компилятор не разрешает этот временный файл. для преобразования в l-значение. Возможно, это временное автоматически определяется как const?
Я действительно передаю временное, но временное-это оболочка для фактического неконстантного l-значения, и ему должно быть позволено свободно изменяться.

Есть ли способ сказать Клангу, чтобы он ослабил эти ограничения?
Можно ли каким-то образом сообщить компилятору, что эти заголовки поступают из библиотеки C++98 и поэтому должны обрабатывать временные файлы, как в C++98? Что-то сродни тому, чтобы делать extern "C"?
Есть способ разрешить преобразование временного значения в l-значение.

Конечно, я могу написать auto b=a(rec) и передать b вместо этого, но это заполняет код кучей именованных временных объектов и бьет по назначению классов-оболочек.

1 3

1 ответ:

Отвечаю сам себе... после некоторых дополнительных исследований кажется,что это поведение продиктовано стандартом, и VS2010 здесь не соответствует.
Это поведение было разработано для предотвращения случайных ошибок, хотя мой вариант использования на самом деле является примером допустимого варианта использования, который запрещен стандартом.

Правило: non-const временные ссылкиНе привязываются кnon -const ссылкам.
Отличие отconst temporaries заключается в том, что вы можете вызвать неконстантные методы на временной основе.
Если такой метод возвращает, например, *this, то Этот результат будет l-значением и, таким образом, будет привязан к неконстантной ссылке.

Для получения дополнительной информации смотрите здесь и здесь.

Как @ Xeo комментирует выше, в C++11 также можно записать преобразователь из r-значения в l-значение: template<class T> T& as_lvalue(T&& v){ return v; } // add 'hazard' icon.
Тем не менее, это следует использовать с особой осторожностью (или вообще не использовать).