I'm trying to assign a lambda to my std::function that contains 1 call to Test for each type specified in the parameter pack, does anyone know how to do this?
template<typename T>
void Test() {
}
template<typename ... Ts>
void Expand() {
std::function<void(void)> func = [Ts] {
for (const auto& p : { Ts... })
Test<Ts...>();
};
}
int main(int argc, char** argv) {
Expand<int, char>();
}
I am trying to have this expand to...
Test<int>();
Test<char>();
CodePudding user response:
template<typename ... Ts>
Ts
here represents types. Template parameters are types.
[Ts] {
// ...
}
A lambda's capture captures values, and discrete objects rather than types. There's no such thing as a capture of types.
for (const auto& p : { Ts... })
Range iteration iterates over values in some container. A braced initialization list is a list values too, not types.
The major confusion here is the confusion between types and values, in C .
If the intent is to generate "call to Test for each type specified in the parameter pack", then the simplest solution is to use C 17's fold expression:
template<typename ... Ts>
void Expand() {
std::function<void(void)> func = [] {
( Test<Ts>(), ...);
};
}
You tagged your question as C 11, but in the year 2022 it is highly likely that your compiler support C 17 as well.
In the unlikely event that you're limited to C 11, a helper throwaway void function can be used as a crutch:
template<typename ...Args>
void ignore_me(Args && ...args)
{
}
template<typename ... Ts>
void Expand() {
std::function<void(void)> func = [] {
ignore_me( (Test<Ts>, 0)...);
};
}
CodePudding user response:
You tagged C 11, so if the newest standard version you have in C 11, you'll need to do it recursively.
template <typename... Ts>
struct ExpandHelper;
template <>
struct ExpandHelper<> {
void operator()() {
// Empty body.
}
}
template <typename T, typename... Ts>
struct ExpandHelper<T, Ts...> {
void operator()() {
Test<T>();
ExpandHelper<Ts...> rest;
rest();
}
}
template <typename... Ts>
void expand() {
std::function<void(void)> func = [] {
ExpandHelper<Ts...> helper;
helper();
};
}
However, if you have access to C 17, you can use fold expressions with the comma operator, and the result is much shorter.
template <typename... Ts>
void expand() {
std::function<void(void)> func = [] {
(Test<Ts>, ...)
};
}