Как разрешить преобразование временного значения в 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 ответ:
Отвечаю сам себе... после некоторых дополнительных исследований кажется,что это поведение продиктовано стандартом, и 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
.
Тем не менее, это следует использовать с особой осторожностью (или вообще не использовать).