2014-03-02 137 views
1

好吧我不知道我是否很好地解釋了標題,所以我只舉一個例子。我試圖想出一個函數來查找一系列浮點數的中位數(並且稍微多一點)。下面是函數:如何通過「自動」返回類型函數的值返回

//get the median of an unordered set of numbers of arbitrary type without modifying the 
    //underlying dataset 
    template <typename InputIterator> 
    auto Median(
     InputIterator const cbegin, 
     InputIterator const cend, 
     bool const abs = false // get the median of the absolute values rather than nominal values 
     ) -> decltype(*cbegin) 
    { 
     typedef std::iterator_traits<InputIterator>::value_type T; 

     std::vector<T> data; 
     data.reserve(std::distance(cbegin, cend)); 

     // get a copy of the values for sorting 
     for (InputIterator it = cbegin; it != cend; ++it) 
     { 
      if (abs) 
       data.push_back(std::abs(*it)); 
      else 
       data.push_back(*it); 
     } 

     // find the median 
     std::nth_element(data.begin(), data.begin() + data.size()/2, data.end()); 

     return data[data.size()/2]; 
    } 

這裏是輸出,如果我嘗試編譯如下:

警告C4172:局部變量的返回地址或臨時

我曾嘗試更換decltype(*cbegin)std::remove_reference<decltype(*cbegin)>::typestd::iterator_traits<decltype(*cbegin)>::value_type但那些不編譯。

有沒有簡單的解決方案呢?如何返回InputIterator指向的類型?

編輯:這是基於反饋的固定的版本:

//get the median of an unordered set of numbers of arbitrary type without modifying the 
    //underlying dataset 
    template <typename RandomAccessIterator> 
    typename std::iterator_traits<RandomAccessIterator>::value_type Median(
     RandomAccessIterator const cbegin, 
     RandomAccessIterator const cend, 
     bool const abs = false // get the median of the absolute values rather than nominal values 
     ) 
    { 
     typedef std::iterator_traits<RandomAccessIterator>::value_type T; 

     std::vector<T> data(cbegin, cend); 

     // find the median 
     std::nth_element(data.begin(), data.begin() + data.size()/2, data.end(), 
      [abs](T const a, T const b) 
     { 
      return abs ? std::abs(b) > std::abs(a) : b > a; 
     }); 

     return data[data.size()/2]; 
    } 
+1

刪除引用順便說一句,如果你堅持'typename'在它前面的'類型名稱的std :: remove_reference'的std :: remove_reference ::類型'應該工作 :: type',但它可能更容易使用'std :: iterator_traits'作爲答案。 –

+1

順便說一句,你可以通過使用['std :: nth_element'](http://en.cppreference.com/w/cpp/algorithm/nth_element)和一個合適的謂詞(取決於abs)來簡化複製。 – juanchopanza

+1

您應該重命名模板類型參數。這個實現不能和_InputIterators_一起工作,這不是_ForwardIterators_。 – nosid

回答

3

您可以使用iterator_traits與模板參數,沒有decltype需要:

template <typename InputIterator> 
typename std::iterator_traits<InputIterator>::value_type 
Median(
    InputIterator const cbegin, 
    InputIterator const cend, 
    bool const abs = false 
); 

typename關鍵字 - 這是少了什麼在你的嘗試中。

2

編譯器告訴你,你正在返回一些臨時的東西,實際上,你是。

decltype(* cbegin)是一個參考(因此您可以編寫代碼,如*it = 12),因此您要返回data內的某個值的引用,這是暫時的。

您可以通過使用std::remove_reference<decltype(*cbegin)>::type