Как вывести параметр шаблона "Fun c" из аргумента конструктора? - PullRequest
0 голосов
/ 01 апреля 2020

Мой код и проблемы следующие:

template <typename T, typename Func> class StepRange {
public:
  template <
      std::enable_if_t<std::is_invocable_r_v<T, Func, const T &>, int> = 0>
  StepRange(T start, T stop, Func func)
      : start_(std::move(start)), stop_(std::move(stop)), val_(start),
        func_(std::move(func)) {}
  template <typename Step>
  StepRange(T start, T stop, Step step)
      : start_(std::move(start)), stop_(std::move(stop)), val_(start), 
        func_(std::function<T(const T &)>{
          [step](const T &val) { return val + step; }}) {}

private:
  T start_, stop_, val_;
  Func func_;
};

auto r = StepRange(1, 1, [](int val) { return val + 1;});
// since c++17 it works fine
auto t = StepRange(1, 1, 1);
// it does not compile and compiler says that it couldn't infer template argument 'Func'

Итак, как я могу использовать некоторые дополнительные методы, чтобы помочь компилятору определить тип 'Fun c'?

1 Ответ

3 голосов
/ 01 апреля 2020

Компилятор не может вывести Func из вашего второго конструктора, поэтому вам нужно указать ему, как определить параметр класса Func, когда первый конструктор недопустим. Вы можете сделать это, добавив руководство по выводам:

template<typename T, typename Step, std::enable_if_t<!std::is_invocable_r_v<T, Step, const T &>, int> = 0>
StepRange(T, T, Step) -> StepRange<T, std::function<T(const T&)>>;

Это выведет Func в std::function<T(const T&)> всякий раз, когда отключен первый конструктор.

Или, если вы действительно хотите только Второй конструктор, который будет использоваться, если типы всех трех аргументов совпадают, вместо этого вы можете написать

template<typename T>
StepRange(T, T, T) -> StepRange<T, std::function<T(const T&)>>;

Конечно, в любом случае нужно рассмотреть некоторые крайние случаи.

...