Q:

Linear compile-time algorithm to convert variadic template into function calls

I have a variadic template function that takes an arbitrary number of arguments.  I need to turn those arguments into a sequence of function calls where the order matters.  The following approach works:
#include <iostream>
#include <typeinfo>
#include <vector>

void printType(const std::type_info& ti) {
    printf("%s\n", ti.name());
}

void expandVariadic() {
}

template<typename First, typename... Rest>
void expandVariadic(const First& first, const Rest&... rest) {
    printType(typeid(First));
    expandVariadic(rest...);
}

int main(int argc, const char* argv[]) {
    expandVariadic(10, "hi", std::cout, std::vector<int>());
    return 0;
}

However, the above code expands to a quadratic number of arguments passed to expandVariadic.  I can force-inline expandVariadic, but that still means quadratic compile time.
Is there a linear-time approach to effect the above?
(They need to be function calls: imagine a logger that generates a sequence of output calls, or something that fills a vector<> with type information.)

A:

struct sink{template<class T>sink(T&&){};};
void run_in_order(){}
template<typename... Fs>
void run_in_order(Fs&&...fs){
  sink _[]={((void)std::forward<Fs>(fs)(),0)...};
  sink{_};// warning elimination
}

use:
template<typename... Ts>
void expandVariadic(const Ts&... ts) {
  run_in_order([&]{printType(typeid(ts));}...);
}

which nicely hides the magic inside run_in_order.  run_in_order takes a sequence of lambdas or other nullary callable objects and invokes them in order from left to right.  This works because evaluation within the {} of the sink _[] line is guaranteed by the C++11 standard to be from left-to-right.
I cast the return value to void then invoke the comma operator with a 0 on the RHS to guarantee that we get a value that can be converted to a sink.  The (void) cast deals with the corner case that the lambda passed in returns an object that overrides operator,.
The downside to this technique is that support for packs inside lambdas is less broad than support for other pack expansions.  A number of compilers I have poked at have been able to do parameter pack expansion of most code, but failed when the parameter packs in question are inside a lambda, and the expansion is outside.

