Реализация Clip () в Eigen - PullRequest
       34

Реализация Clip () в Eigen

0 голосов
/ 22 декабря 2019

У меня есть код, который ограничивает какое-то значение между диапазоном с центром в 0, как показано ниже.

Eigen::VectorXd a;
Eigen::VecotrXd b;
a = a.cwiseMin(b).cwiseMax(-b);  // no temporary created here?

Я хочу выделить логику в функцию. Одно решение:

Eigen::VectorXd Clip(const Eigen::VectorXd& a, const Eigen::VectorXd& b);

a = Clip(a, b);

Но я полагаю, что это неэффективно, так как оно создает дополнительный временный файл?

Другое решение:

void Clip(Eigen::Ref<Eigen::VectorXd> a, const Eigen::VectorXd& b) {
  a = a.cwiseMin(b).cwiseMax(-b);
}

Но иногда это неудобно использовать:

void SomeFunctionSignatureICannotChange(const Eigen::VectorXd& a, const Eigen::VectorXd& b) {
  // Eigen::VectorXd a_clipped = Clip(a, b); would be cleaner.
  Eigen::VectorXd a_clipped;
  Clip(a_clipped, b);
}

Лучшее решение, которое я могу придумать:

template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
          const Eigen::ArrayBase<DerivedB>& bound)
          -> decltype(v.min(bound).max(-bound)) {
  return v.min(bound).max(-bound);
}

(я полагаю, что в данном случае 'auto' - это хорошо, а не то, что общие ловушки предупрежден против?)

Однако код кажется сложным и немного сложным. Например, тип конечного возврата не рекомендуется в руководстве по стилю Google здесь :

Используйте новую форму типа конечного возврата только в тех случаях, когда это требуется (например, в лямбдах) илигде, помещая тип после списка параметров функции, он позволяет вам писать тип в гораздо более удобочитаемой форме. Последний случай должен быть редким;Это в основном проблема в довольно сложном коде шаблона, который в большинстве случаев не рекомендуется.

В качестве альтернативы, если я удаляю конечный тип возврата, срабатывает вывод типа возврата функции. Но руководство по стилю Google, похоже,также препятствует выводу возвращаемого типа функции в открытых заголовках здесь

Кроме того, используйте его только в том случае, если функция или лямбда имеют очень узкую область видимости, потому что функции с выведенными типами возврата неопределить границы абстракции: реализация - это интерфейс. В частности, публичные функции в заголовочных файлах почти никогда не должны были выводить возвращаемые типы.

Я новичок в Eigen и C ++, поэтому не уверен, что что-то пропустил. Надеюсь учиться на все комментарии и предложения. Спасибо!

1 Ответ

2 голосов
/ 22 декабря 2019

Я подтверждаю, что a = a.cwiseMin(b).cwiseMax(-b); не создает никаких временных. В вашем случае настоятельно рекомендуется использовать auto тип возвращаемого значения, и я также утверждаю, что ваш сценарий использования является вполне допустимым исключением из вышеупомянутых правил:

  • Запись типа возврата в явном виде будетНочные кошмары и ошибки.
  • Это очень короткая функция, которая должна быть встроенной. Таким образом, ожидается, что он будет объявлен и определен одновременно. Поэтому второе правило на самом деле не применяется.

В C ++ 14 вы даже можете опустить избыточность:

template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
          const Eigen::ArrayBase<DerivedB>& bound)
{
  return v.min(bound).max(-bound);
}
...