具有许多不同类型的 C++ 调用函数
C++ call function with many different types
我有一个重载函数,我必须用许多不同的类型调用它。简单的做法是:
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);
这是怎么做到的?
有了一些 boiler-plate to obtain a tuple 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);
});
}
如果你想有一个预定义的类型序列,如果你不想创建带参数的元组,你可以使用 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);
}
有std::tuple
和std::apply
std::tuple<uint8_t, uint16_t, double> tup{};
std::apply([](const auto&... arg) { (doSomething(arg), ...); }, tup);
我有一个重载函数,我必须用许多不同的类型调用它。简单的做法是:
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);
这是怎么做到的?
有了一些 boiler-plate to obtain a tuple 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);
});
}
如果你想有一个预定义的类型序列,如果你不想创建带参数的元组,你可以使用 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);
}
有std::tuple
和std::apply
std::tuple<uint8_t, uint16_t, double> tup{};
std::apply([](const auto&... arg) { (doSomething(arg), ...); }, tup);