Используйте Параметры останова для представления неопределенного числа аргументов в качестве массива.
function sumTwoSmallestNumbers(...numbers) {
const filter = numbers.filter(x => x > -1).sort((a, b) => a - b);
return filter[0] + filter[1];
}
console.log(sumTwoSmallestNumbers(544, 32654, 34297, 9237, 343, 98));
Крайне важно, чтобы сгенерированный код был максимально эффективным.
blockquote>Еще одно замечание, касающееся вашего примера: вы должны убедиться, что производительность не страдает от передачи аргументов функции по значению. То же самое для возвращаемого значения.
Есть ли способ сделать это, избегая как переменных времени выполнения, так и вспомогательной функции?
blockquote>Вы можете реализовать вспомогательные функции многократного использования. В качестве примера рассмотрим следующий код.
static_assert(__cplusplus >= 201703L, "example written for C++17 or later"); #include <cstddef> #include <array> #include <type_traits> #include <utility> namespace detail { template<std::size_t... inds, class F> constexpr void gen_inds_impl(std::index_sequence<inds...>, F&& f) { f(std::integral_constant<std::size_t, inds>{}...); } }// detail template<std::size_t N, class F> constexpr void gen_inds(F&& f) { detail::gen_inds_impl(std::make_index_sequence<N>{}, std::forward<F>(f)); } // the code above is reusable template< std::size_t... inds_out, class T, std::size_t size_out, std::size_t size_in > constexpr std::array<T, size_out> insert1( std::array<T, size_out> out, std::array<T, size_in> in ) { static_assert((... && (inds_out < size_out))); static_assert(sizeof...(inds_out) <= size_in); gen_inds<sizeof...(inds_out)>([&] (auto... inds_in) { ((out[inds_out] = in[inds_in]), ...); }); return out; }
Аналогичной альтернативой является
static_for
подход:static_assert(__cplusplus >= 201703L, "example written for C++17 or later"); #include <cstddef> #include <array> #include <type_traits> #include <utility> namespace detail { template<std::size_t... inds, class F> constexpr void static_for_impl(std::index_sequence<inds...>, F&& f) { (f(std::integral_constant<std::size_t, inds>{}), ...); } }// detail template<std::size_t N, class F> constexpr void static_for(F&& f) { detail::static_for_impl(std::make_index_sequence<N>{}, std::forward<F>(f)); } // the code above is reusable template< std::size_t... inds_out, class T, std::size_t size_out, std::size_t size_in > constexpr std::array<T, size_out> insert2( std::array<T, size_out> out, std::array<T, size_in> in ) { static_assert(sizeof...(inds_out) >= 1); static_assert((... && (inds_out < size_out))); static_assert(sizeof...(inds_out) <= size_in); constexpr std::size_t N = sizeof...(inds_out); static_for<N>([&] (auto n) { // note the constexpr constexpr std::size_t ind_out = std::array{inds_out...}[n]; constexpr std::size_t ind_in = n; out[ind_out] = in[ind_in]; }); return out; }
Я не думаю, что это возможно, избегая как переменных времени выполнения, так и вспомогательной функции (надеясь, что кто-то может это опровергнуть).
И мне очень нравится ваше второе решение, но ... как насчет использования итераторов для y
(если y
поддерживает cbegin()
и итераторы, очевидно).
Что-то как (осторожно: код не проверен)
template <std::size_t Ii...., std::size_t Xsize, std::size_t Ysize>
constexpr container<Xsize> insert(container<Xsize> x, container<Ysize> const & y) {
auto it = y.cbegin();
((x[Ii] = *it++), ...);
return x;
}
Это почти ваше первое решение, но доступ к y
, увеличивающему итератор, должен быть (я полагаю, для последовательного обхода, для некоторых контейнеров) более эффективно (немного более эффективно), чем использование operator[]()
.
Но я также полагаю, что с хорошим оптимизатором заметной разницы нет.