2017-02-17 8 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はそれを名前initを与えて、その型のオブジェクトを構築し、デフォルト、デフォルトでstd::iterator_traits<BidirIt>::value_typeになりたいです。

1行に変数の型の一部をフィッティングの問題を解決した後、私はそのコンパイラが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::accumulatehttp://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

関連する問題