Reputation: 1680
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>();
Upvotes: 2
Views: 506
Reputation: 1680
template<typename T>
void Test() {
using namespace boost::typeindex;
std::cout << stl_type_index(typeid(T)).pretty_name() << std::endl;
}
template<typename...Ts>
void Expand() {
(Test<Ts>(), ...);
}
int main(int argc, char** argv) {
Expand<int, char>();
}
outputs...
int
char
Upvotes: 1
Reputation: 118425
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)...);
};
}
Upvotes: 1
Reputation: 70297
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>, ...)
};
}
Upvotes: 1