С ++ функциональный дизайн - PullRequest
0 голосов
/ 23 декабря 2019

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

Примером может служить следующий фрагмент функции, который разбивает последовательный контейнер на N частей равного размера (предварительное условие: фрагменты можно разделить). Можно ли написать это в следующей форме

template <typename T, std::size_t N>
array<T, N> equal_split(const T& x, array<T, N> result = {}) {
  for (int i = 0; i < N; ++i)
    std::copy(begin(x) + i * size(x) / 3, begin(x) + (i + 1) * size(x) / 3, std::back_inserter(result[i]));
  return result;
}

или лучше написать как

template <typename T, std::size_t N>
array<T, N> equal_split(const T& x) {
  array<T, N> result = {};
  for (int i = 0; i < N; ++i)
    std::copy(begin(x) + i * size(x) / 3, begin(x) + (i + 1) * size(x) / 3, std::back_inserter(result[i]));
  return result;
}

1 Ответ

1 голос
/ 23 декабря 2019

Мне нужно объявить начальное значение аккумулятора

Если это просто деталь реализации, то скрыть его от интерфейса.

, если имеют смысл разные начальные значения, затем вы можете добавить его в интерфейс.

В вашем примере подпись будет:

template <std::size_t N, typename Container>
array<Container, N> equal_split(const Container&);
  • Переименовать T в более значимое Container
  • size_t N во-первых, не нужно предоставлять франшизу Container
  • Нет параметров по умолчанию, поскольку начальное значение было просто подробностью реализации.
...