2017-02-17 18 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

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

  • Нет связанных вопросов^_^