2017-02-17 40 views
1

這裏是憎惡如何在函數中默認構造迭代器的value_type作爲默認參數?

template <typename BidirIt, typename OutputIt, typename T, 
      typename BinaryDoOp, typename BinaryUndoOp> 
void sliding_window(BidirIt first, BidirIt last, OutputIt d_first, 
        typename std::iterator_traits<BidirIt>::difference_type length, 
        T init = typename std::iterator_traits<BidirIt>::value_type(), 
        BinaryDoOp op = std::plus<>{}, 
        BinaryUndoOp undo = std::minus<>{}) 

所以我想T是默認和默認std::iterator_traits<BidirIt>::value_type構建類型賦予它一個名稱init的對象。

解決一個擬合線的一些變量類型的問題後,我發現,編譯器不能推斷T,這裏是它究竟說:

error: no matching function for call to 'sliding_window' sliding_window(v.begin(), v.end(), output.begin(), window_length/, 0, std::plus<>(), std::minus<>()/);

note: candidate template ignored: couldn't infer template argument 'T' void sliding_window(BidirIt first, BidirIt last, OutputIt d_first,

我的編譯器是鐺++ - 3.9 。

呼叫站點代碼:

std::vector<int> v(window_length + window_count - 1); 
std::iota(v.begin(), v.end(), 0); 

std::vector<int> output(window_count); 
std::vector<int> correct_result{3, 6, 9, 12}; 

sliding_window(v.begin(), v.end(), output.begin(), window_length/*, 0, std::plus<>(), std::minus<>()*/); 

在評論部分是註釋掉的代碼工作正常。

根據我對模板的瞭解,它應該能夠推斷出該類型,因爲它實際上是一個默認構造函數調用,應該產生std::iterator_traits<BidirIt>::value_type。我對功能模板化類型時默認參數類型的工作方式有任何誤解嗎?

問題:如何解決?也可以給它增加一些解釋。

回答

4

無法從默認模板參數中推斷出模板類型:C++14 lambda's default argument type deduction depending on preceding arguments。至於如何解決它,你將需要默認類型:

template <typename BidirIt, typename OutputIt, 
    typename T = typename std::iterator_traits<BiDirIt>::value_type, 
    typename BinaryDoOp = std::plus<>, 
    typename BinaryUndoOp = std::minus<>> 
void sliding_window(BidirIt first, BidirIt last, OutputIt d_first, 
       typename std::iterator_traits<BidirIt>::difference_type length, 
       T init = T{}, 
       BinaryDoOp op = BinaryDoOp{}, 
       BinaryUndoOp undo = BinaryUndoOp{}) 

另一種辦法也有重載函數,其中用較少的模板參數的那些/參數調用者提供更多處理在通話現場默認。這是std::accumulate使用的方法:http://en.cppreference.com/w/cpp/algorithm/accumulate。然後你會有多個功能,所以在那裏有一些重複,但每一個都更可讀。

+0

感謝您提供更多信息。 Jarod的版本編譯正確,我相信它是標準一致的,所以可能會遺漏類型的rhs =是一個好主意? – Incomputable

+0

@ Jarod42謝謝你的糾正。 –

1

它應該是:

template <typename BidirIt, 
      typename OutputIt, 
      typename T = typename std::iterator_traits<BidirIt>::value_type, 
      typename BinaryDoOp = std::plus<>, 
      typename BinaryUndoOp = std::minus<>> 
void sliding_window(BidirIt first, 
        BidirIt last, 
        OutputIt d_first, 
        typename std::iterator_traits<BidirIt>::difference_type length, 
        T init = {}, 
        BinaryDoOp op = {}, 
        BinaryUndoOp undo = {}) 

模板類型不是從默認值推斷。 所以你必須手動設置默認類型。

+0

謝謝,它的工作原理。對未來的讀者來說,解釋會很好,但從外觀上看,它們看起來很明顯 – Incomputable