[英]Function operating on each type of a variadic template typelist
I have defined a typelist like this:我已经定义了一个这样的类型列表:
template <typename ... Types> struct typelist {};
using my_list = typelist<int, double, bool, float>;
Now I have a function template, eg现在我有一个函数模板,例如
template<typename T>
void foo() {
std::cout << typeid(T).name() << std::endl;
}
and want to call this for every type in the typelist:并想为类型列表中的每个类型调用它:
foo<int>();
foo<double>();
foo<bool>();
foo<float>();
I tried to find a recursive way to solve this, but I am having trouble to define the correct, probably nested, variadic templates for the required foo functions.我试图找到一种递归方法来解决这个问题,但是我无法为所需的 foo 函数定义正确的、可能是嵌套的、可变参数模板。 Do you have any hints for a neat solution to this problem?你有什么关于这个问题的巧妙解决方案的提示吗?
template<class... Types> auto foo_foreach(typelist<Types...>) {
return (foo<Types>(), ...);
}
int main() {
foo_foreach(my_list{});
}
For a real oldschool, well, use template recursion you've attempted before:对于真正的老派,使用您之前尝试过的模板递归:
void foo_foreach(typelist<>) {}
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>);
template<class Head, class... Tail> void foo_foreach(typelist<Head, Tail...>) {
foo<Head>();
foo_foreach(typelist<Tail...>{});
}
Here is a c++20 answer only that uses lambda template.这是一个仅使用 lambda 模板的c++20答案。
template <typename... Ts, typename C>
constexpr void for_types(C&& c) {
(c.template operator()<Ts>(), ...);
}
for_types<int, float, char>([]<typename T>()
{
std::cout << typeid(T).name() << std::endl;
});
If you need this to work with C++14 then you can use the initializer_list
trick to avoid a C++17 fold expression.如果您需要它与 C++14 一起使用,那么您可以使用initializer_list
技巧来避免 C++17 折叠表达式。 This will hopefully be cheaper to compile than a recursive approach:这有望比递归方法更便宜:
template<class... Ts> void foo_foreach(typelist<Ts...>) {
(void) std::initializer_list<int>{(foo<Ts>(), 0)...};
}
int main() {
foo_foreach(my_list{});
}
Godbolt example: https://godbolt.org/z/o91Th466s Godbolt 示例: https ://godbolt.org/z/o91Th466s
There is a good explanation of the initializer_list
trick athttps://blog.tartanllama.xyz/exploding-tuples-fold-expressions/在https://blog.tartanllama.xyz/exploding-tuples-fold-expressions/ 上有关于initializer_list
技巧的很好解释
From that article:从那篇文章:
[...] parameter packs can only be expanded in contexts which expect a syntactic list, such as initializers and function call arguments. [...] 参数包只能在需要语法列表的上下文中扩展,例如初始化程序和函数调用参数。 You can't just expand them bare in a function body.你不能只是在函数体中裸露它们。 In C++17, this problem has a nice solution, but prior to that we need to use some pretty horrible hacks.在 C++17 中,这个问题有一个很好的解决方案,但在此之前我们需要使用一些非常可怕的技巧。 [...] one possibility [...] uses
std::initializer_list
to create a context in which the parameter pack can be expanded. [...] 一种可能性 [...] 使用std::initializer_list
创建一个可以扩展参数包的上下文。The trick is the
, 0
inside theinitializer_list
initializer, which evaluates the function call, and uses 0 as the initializer value.诀窍是, 0
在initializer_list
程序中,它评估函数调用,并使用 0 作为初始化程序值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.