Функция вызова C ++ со многими различными типами - PullRequest
11 голосов
/ 06 мая 2019

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

uint8_t a;
uint16_t b;
//....
double x;

doSomething(a);
doSomething(b);
//...
doSomething(x);

сжатое выражение этих вызовов может быть выполнено с помощью шаблона с переменным числом аргументов, как описано в этом Q & A .Код будет выглядеть примерно так:

auto doSomethingForAllTypes = [](auto&&... args) {
    (doSomething(args), ...);
};

uint8_t a;
uint16_t b;
//....
double x;

doSomethingForAllTypes(a, b, ... ,x);

Но мне придется делать это во многих местах кода, поэтому я хотел бы определить список типов только один раз.Я хотел бы иметь код, который концептуально выглядит следующим образом:

auto doSomethingForAllTypes = [](auto&&... args) {
    (doSomething(args), ...);
};

someContainer allTypesNeeded(uint8_t, uint16_t, ... double);

doSomethingForAllTypes(allTypesNeeded);

Как это можно сделать?

Ответы [ 3 ]

10 голосов
/ 06 мая 2019

С некоторой плитой для получения кортежа foreach вы можете реализовать то, что вы хотите, следующим образом:

#include <tuple>
#include <utility>

namespace detail
{
    template<typename T, typename F, std::size_t... Is>
    void for_each(T&& t, F f, std::index_sequence<Is...>)
    {
        ( static_cast<void>(f(std::get<Is>(std::forward<T>(t)))),... );
    }
}

template<typename... Ts, typename F>
void for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
    detail::for_each(t, f, std::index_sequence_for<Ts...>{});
}

int main() {
    std::tuple<uint8_t, uint16_t, double> tup{};
    for_each_in_tuple(tup, [](auto&& arg) {
        doSomething(arg);
    });
}

Живой пример

5 голосов
/ 06 мая 2019

Если вы хотите иметь предопределенную последовательность типов, вы можете использовать подход TypeList, если вы не хотите создавать кортежи с аргументами:

#include <type_traits>
#include <utility>

void doSomething(int)
{
}

void doSomething(double)
{
}

template <typename... Args>
void doSomething(Args&&... args)
{
    (doSomething(std::forward<Args>(args)), ...);
}

template <typename ...Args>
struct TypeList{};

template <typename T>
struct DoSomethingHelper;

template <typename ...Args>
struct DoSomethingHelper<TypeList<Args...>>
{
    static void doSomething(Args&&... args)
    {
        ::doSomething(std::forward<Args>(args)...);
    }
};

template <typename T, typename ...Args>
void doSomethingForTypes(Args&&... args)
{
    DoSomethingHelper<T>::doSomething(std::forward<Args>(args)...);
}

int main()
{
    using MyTypeList = TypeList<int, double, int>;

    doSomethingForTypes<MyTypeList>(1, 1.0, 2);
}
1 голос
/ 06 мая 2019

С std::tuple и std::apply

std::tuple<uint8_t, uint16_t, double> tup{};
std::apply([](const auto&... arg) { (doSomething(arg), ...); }, tup);
...