Передача универсальной функции для работы с однородными типами - PullRequest
1 голос
/ 05 мая 2019

Допустим, у меня есть класс, состоящий из однородных типов:

struct Homog {
    int a;
    double b;
    std::string c;
};

Вот функция, которая вычисляет "поэлементную мин" 1 двух экземпляров этого класса:

Homog min(const Homog& l, const Homog& r) {
  return {
      std::min(l.a, r.a),
      std::min(l.b, r.b),
      std::min(l.c, r.c),
  };
}

Отлично.

Теперь я хочу вычислить max вместо min . Код идентичен, но с std::min заменен на std::max. Я не хотел бы дублировать его, скорее, я хотел бы иметь один общий метод "поэлементного применения", а затем min и max просто вызовите его с соответствующим функтором:

Homog apply(const Homog& l, const Homog& r, ?? op) {
  return {
      op(l.a, r.a),
      op(l.b, r.b),
      op(l.c, r.c),
  };
}

Homog min(const Homog& l, const Homog& r) {
    return apply(l, r, std::min);
}

Homog max(const Homog& l, const Homog& r) {
    return apply(l, r, std::max);
}

Конечно, приведенный выше код не работает, потому что я не знаю, как объявить op. Это не обычный универсальный объект-функтор, потому что он должен работать с разными типами.

Могу ли я сделать то, что я хочу, каким-то образом передавая что-то вроде «call op для каждого участника: не волнуйтесь, это разрешится на что-то для каждого типа»?


Возможно, использование min() здесь не лучшее имя, потому что оно не ведет себя так же, как std::min, который всегда возвращает один из двух заданных объектов: этот метод возвращает новый объект, который в общем случае не является такой же, как любой из двух входов, но скорее смесь их значений элементов.

1 Ответ

2 голосов
/ 05 мая 2019

Конечно, приведенный выше код не работает, потому что я не знаю, как объявить ор.Это не обычный универсальный объект-функтор, поскольку он должен работать с различными типами.

Обычно эту проблему обходят с помощью функционала с шаблоном operator().

Запускиз C ++ 14 (которые вводят общие лямбды) просто следующим образом

template <typename F>
Homog apply(const Homog& l, const Homog& r, F const & op) {
  return {
      op(l.a, r.a),
      op(l.b, r.b),
      op(l.c, r.c),
  };
}

Homog min(const Homog& l, const Homog& r) {
    return apply(l, r, [](auto const & a, auto const & b){ return std::min(a, b); });
}
...