Вопрос

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

template<typename... Int> // a bunch of integral types (e.g. int, size_t, char)
void ForwardToFuncIncreased(Int... ints) {
   static_assert(sizeof...(Ints) == std::tuple_size<decltype(summands_)>::value,
                 "Incorrect number of integral types provided");

   Func( (ints + std::get<PARAM_INDEX(ints)>(summands_))... ); // failed attempt
}

где summands_ является переменной-членом типа std::tuple или std::array (можете предположить и то, и другое).Основное требование заключается в том, что у него не должно быть накладных расходов во время выполнения по сравнению с:

Func(int0 + std::get<0>(summands_), int1 + std::get<1>(summands_), ...);

(Представьте, что я перегружаю функцию до N параметры шаблона).

Если это невозможно сделать без необходимый накладные расходы во время выполнения, я готов внести некоторые изменения (особенно.способом хранения дополнительных материалов в моем классе или изменения типа).

Примечание:Я намерен не извлекать индексы аргументов шаблона, а, надеюсь, добиться того, что мне нужно, без этого.

Это было полезно?

Решение

В C++14 вы сможете сделать следующее, очень похожее на вашу первоначальную попытку:

template<typename... Ns, size_t... Is>
void ForwardToFuncIncreasedImpl(Ns... nums, std::index_sequence<Is...>)
{
    Func( (nums + std::get<Is>(summands_))... );
}

template<typename... Ns>
void ForwardToFuncIncreased(Ns... nums)
{
    ForwardToFuncIncreasedImpl(nums..., std::index_sequence_for<Ns...>());
}

Тем временем вы можете найти или написать свою собственную реализацию index_sequence.

Или сделайте что-то вроде этого:Сначала делаю std::make_tuple(ints...) так что у нас есть два кортежа, которые мы хотим просуммировать (или кортеж и std::array).Затем, используя шаблон, продемонстрированный Андреем Александреску в Путь взрывающегося кортежа чтобы расширить сумму в пакет параметров, который передается Func.

template <int N>
struct Pairwise;

template <>
struct Pairwise<0>
{
    template <typename F, typename T, typename U, typename... Args>
    static void Sum(F f, T const&, U const&, Args... sums)
    {
        f(sums...);
    }
};

template <int N>
struct Pairwise
{
    template <typename F, typename T, typename U, typename... Args>
    static void Sum(F f, T const& a, U const& b, Args... sums)
    {
        Pairwise<N - 1>::Sum(f, a, b, std::get<N - 1>(a) + std::get<N - 1>(b), sums...);
    }
};

template <typename... Ns>
void ForwardToFuncIncreased(Ns... nums)
{
    Pairwise<sizeof...(Ns)>::Sum(Func, std::make_tuple(nums...), summands_);
}

Это также возможно сделать без первоначального make_tuple:

template <typename... Ns>
struct Pairwise;

template <>
struct Pairwise<>
{
    template <typename F, typename T, typename... Args>
    static void Sum(F f, T const&, Args... sums)
    {
        f(sums...);
    }
};

template <typename N0, typename... Ns>
struct Pairwise<N0, Ns...>
{
    template <typename F, typename T, typename... Args>
    static void Sum(F f, N0 num0, Ns... nums, T const& a, Args&&... sums)
    {
        Pairwise<Ns...>::Sum(f, nums..., a, sums..., num0 + std::get<sizeof...(Args)>(a));
    }
};

template <typename... Ns>
void ForwardToFuncIncreased(Ns... nums)
{
    Pairwise<Ns...>::Sum(Func, nums..., summands_);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top