问题
I have a parameter pack full of default constructable and then callable objects (like the ExampleFunctor
) and want to call all of them in order (left to right). If the return type is anything besides void I can use an initializer list to do this:
struct ExampleFunctor{
void operator()(){someGlobal = 4;}
};
template<typename... Ts>
struct CallThem {
void operator()(){
auto list = {Ts()()...};
}
}
however if the return type is void this trick does not work.
I could wrap all the Ts in a wrapper returning an int but that seems overkill and this code will be ultimately running on a cortex M3 with 32K of flash so the extra function call overhead of the wrapper is a pain if I compile the unit in debug mode (and debugging in release mode makes my brain hurt).
Is there a better way?
回答1:
With the comma operator:
int someGlobal;
struct ExampleFunctor{
void operator()(){someGlobal = 4;}
};
template<typename... Ts>
struct CallThem {
void operator()(){
int list[] = {(Ts()(),0)...};
(void)list;
}
};
int main()
{
CallThem<ExampleFunctor, ExampleFunctor>{}();
}
Btw I'm not using an initializer_list
here but just an array; try yourself which one / if any of them can be thrown away by the compiler. The (void)list
is to suppress a warning (unused variable).
回答2:
The compiler should be able to optimize away the function calls here:
template <typename H, typename... Tail>
void call(H head, Tail... tail) {
head();
call(tail...);
}
template <typename T>
void call(T fn) {
fn();
}
template <typename... Args>
void callThem() {
call(Args()...);
}
But this is untested. Check the generated assembly for your platform.
回答3:
You may use something like:
template<typename... Ts>
struct CallThem;
template<>
struct CallThem<> { void operator()() const {} };
template<typename Tail, typename... Queue>
struct CallThem<Tail, Queue...>
{
void operator()() const {
Tail()();
CallThem<Queue...>()();
}
};
来源:https://stackoverflow.com/questions/19860851/how-should-i-call-all-functions-in-a-variadic-parameter-pack-if-the-function-ret