Должны ли шаблонные математические функции принимать значения или константные ссылки?

Предположим, я хочу реализовать некоторую простую математическую функцию; например, предположим, что это переопределение (C ++ 17) std::clamp: Эта функция принимает число, нижнюю границу и верхнюю границу и устанавливает число в одну из этих границ, если она выходит за пределы диапазона, который они определяют. Если это конкретный числовой тип, скажем, intЯ бы написал:

constexpr int clamp(int x, int lower_bound, int upper_bound)
{
return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

но если это шаблон, я вижу, что пример реализации что, вероятно, то, что стандарт будет использовать const&а не ценности. Итак, что упрощает цитирование, что-то вроде:

template <typename T>
constexpr T clip(const T& x, const T& lower_bound, const T& upper_bound)
{
return x < lower_bound ? lower_bound : ( upper_bound < x ? upper_bound : x );
}

Мои вопросы:

  • Есть ли какая-то польза от использования констант Tкакие простые числовые типы?
  • То же самое, для типов, которые являются некоторой абстрактной вещью, оборачивающей одно число в элемент данных (например, std::chrono длительность)?
  • Почему это (и это вообще) лучшая идея взять const& тогда значение в общем случае любой относительно простой, (constexpr?), свободной от побочных эффектов математической функции?

Заметки:

  • Я понимаю, принимая const& может иметь смысл, когда у вас есть, скажем, какой-то тип k-мерного вектора, или boost::rationals и другие числовые типы; но даже тогда, не будет ли компилятор оптимизировать копирование?
  • я не спрашивать о любой произвольной функции C ++ и о том, должна ли она просто принимать параметры по значению, это было бы плохой идеей.

1

Решение

  • Есть ли какая-то польза от использования констант Tкакие простые числовые типы?

Нет.

  • То же самое, для типов, которые являются некоторой абстрактной вещью, оборачивающей одно число в элемент данных (например, std::chrono длительность)?

Нет.

  • Почему это (и это вообще) лучшая идея взять const& чем значение в общем случае любой относительно простой (constexpr?) математической функции без побочных эффектов?

Представьте себе тип bigint, который использует динамическое размещение; копирование такого типа стоит дорого.

  • Разве компилятор не оптимизирует копирование?

Только если это может доказать, что копирование значения не имеет побочного эффекта, что трудно сделать, если весь задействованный код не виден компилятору. (Итак, если ваш bigint использует, скажем, GMP, вам не повезло.)

3

Другие решения

Есть ли какая-то польза от использования констант Tкакие простые числовые типы?

Нет, я так не думаю, но штрафов тоже нет.

То же самое, для типов, которые являются некоторой абстрактной вещью, оборачивающей одно число в элемент данных (например, std::chrono duration)?

То же самое.

Почему это (и это вообще) лучшая идея взять const& тогда значение в общем случае?

Стандартные библиотечные алгоритмы предназначены не только для основных типов, но и для пользовательских типов, которые могут быть недешевыми для копирования. Для этих типов, используя const& Избегает штрафов за копирование, не нанося вреда обычным типам.

2

По вопросам рекламы [email protected]