2016-04-11 3 views
8

Я использую GCC 4.7.2 и Boost 1.58.0 на SUSE Enterprise Linux 11. У меня есть следующий фрагмент кода, который в основном проходит через список полигонов, чтобы вычислить их длина ширина. Я вижу странный вывод при использовании ключевого слова «auto» с помощью функции std :: minmax. Для сравнения я также объявляю вторую переменную, в которой типы явно объявлены (т. Е. Dim vs dim1).Наблюдение за странным поведением с помощью «auto» и std :: minmax

namespace gtl = boost::polygon; 
typedef gtl::polygon_90_data<int> LayoutPolygon; 
typedef gtl::rectangle_data<int> LayoutRectangle; 
static LayoutFeatureVec 
calc_stats(LayoutPolygonSet const& lp) 
{ 
    LayoutFeatureVec v; 
    LayoutFeature f; 
    LayoutRectangle y; 
    for (LayoutPolygon const& p : lp) { 
     // Compute bounds. 
     gtl::extents(y, p); 

     // Get width/length (shorter/longer). 
     // FIXME: Why does this not work with auto?? 
     cout << gtl::delta(y, gtl::HORIZONTAL) << " " << gtl::delta(y, gtl::VERTICAL) << endl; 

     auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL), 
          gtl::delta(y, gtl::VERTICAL)); 

     std::pair<int, int> dim1 = std::minmax(gtl::delta(y, gtl::HORIZONTAL), 
              gtl::delta(y, gtl::VERTICAL)); 

     cout << dim.first << " " << dim.second << endl; 
     cout << dim1.first << " " << dim1.second << endl; 

     <snip> 
     v.push_back(f); 
    } 

    return v; 
} 

Для первой итерации этого цикла ожидаемый результат является правильным.

380 420 
380 420 
380 420 

Однако, если я закомментировать «DIM1» и повторите тот же код (то есть, просто авто затемнения), я получаю странные результаты с стандом :: MINMAX.

380 420 
140737295994126 140737295994126 

Что я здесь делаю неправильно?

Вот минимальный пример (отредактированный на основе ответа ниже).

#include <iostream> 
#include <algorithm> 
#include <boost/polygon/polygon.hpp> 

using namespace std; 

namespace gtl = boost::polygon; 
using namespace gtl::operators; 

int main(int argc, char** argv) 
{ 
    gtl::rectangle_data<int> x(0,0,5,5); 

    auto dim = std::minmax(gtl::delta(x, gtl::HORIZONTAL), gtl::delta(x, gtl::VERTICAL)); 
    cout << dim.first << " " << dim.second << endl; 

    return 0; 
} 

ответ

13

Это один из тех случаев, когда не использовать auto как спецификатор типа. std::minmax возвращает пару ссылок:

template< class T > 
std::pair<const T&,const T&> minmax(const T& a, const T& b); 

Вот что auto выведут. Но delta() возвращает временный. Поэтому, когда вы пишете:

auto dim = std::minmax(gtl::delta(y, gtl::HORIZONTAL), 
         gtl::delta(y, gtl::VERTICAL)); 

dim держит две оборванные ссылки. Но когда вы пишете:

std::pair<int, int> dim1 = std::minmax(...); 

Вы просто держите значения напрямую. Вот почему это работает, но auto этого не делает. Дополнительное преобразование, которое вы выполняете, препятствует тому, чтобы вы держали болтающиеся ссылки.


В качестве альтернативы, и для полноты картины, можно использовать другую перегрузку minmax, которая не возвращает ссылки:

template< class T > 
std::pair<T,T> minmax(std::initializer_list<T> ilist); 

который только включает в себя некоторые дополнительные фигурные скобки:

auto dim2 = std::minmax({gtl::delta(y, gtl::HORIZONTAL), 
         gtl::delta(y, gtl::VERTICAL)}); 

Но Я бы предложил просто явно называть тип. Это кажется менее подверженным ошибкам.

Смежные вопросы