#include <type_traits>
#include <iostream>
#include <string>
#include <typeinfo>
#include <utility>
#include <tuple>
struct context{};
template<class T> auto pass(const context& c) noexcept
{
using arg = ::std::remove_cv_t<
::std::remove_reference_t<T>
>;
std::cout << "type = " << typeid(T).name() << std::endl;
return arg{};
}
void some_function(int v1, bool v2, const std::string& v3) noexcept
{
std::cout << "call("
<< v1 << ", "
<< std::boolalpha << v2 <<" , \""
<< v3 <<"\" );\n";
}
template<typename F, typename ArgsTuple, std::size_t ...Indices>
auto apply(F && f, ArgsTuple && args, std::index_sequence<Indices...>) {
return std::forward<F>(f)(std::get<Indices>(std::forward<ArgsTuple>(args))...);
}
template<class... Args> void expand(const Args&...)
{
using tuple_type = std::tuple<std::remove_cv_t<decltype(pass<Args>(std::declval<context>()))>...>;
context ctx;
tuple_type args { pass<Args>(ctx)... };
apply(some_function,
std::move(args),
std::make_index_sequence<sizeof...(Args)> {});
}
int main()
{
expand(42, true, std::string { "answer" });
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx0eXBlaW5mbz4KI2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDx0dXBsZT4KCgpzdHJ1Y3QgY29udGV4dHt9OwoKdGVtcGxhdGU8Y2xhc3MgVD4gYXV0byBwYXNzKGNvbnN0IGNvbnRleHQmIGMpIG5vZXhjZXB0CnsKICAgIHVzaW5nIGFyZyA9IDo6c3RkOjpyZW1vdmVfY3ZfdDwKICAgICAgICA6OnN0ZDo6cmVtb3ZlX3JlZmVyZW5jZV90PFQ+IAogICAgPjsKICAgIAogICAgc3RkOjpjb3V0IDw8ICJ0eXBlID0gIiA8PCB0eXBlaWQoVCkubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKICAgIHJldHVybiBhcmd7fTsKfQoKdm9pZCBzb21lX2Z1bmN0aW9uKGludCB2MSwgYm9vbCB2MiwgY29uc3Qgc3RkOjpzdHJpbmcmIHYzKSBub2V4Y2VwdAp7CiAgICBzdGQ6OmNvdXQgPDwgImNhbGwoIiAKICAgICAgICA8PCB2MSA8PCAiLCAiIAogICAgICAgIDw8IHN0ZDo6Ym9vbGFscGhhIDw8IHYyIDw8IiAsIFwiIiAKICAgICAgICA8PCB2MyA8PCJcIiApO1xuIjsKfQoKCnRlbXBsYXRlPHR5cGVuYW1lIEYsIHR5cGVuYW1lIEFyZ3NUdXBsZSwgc3RkOjpzaXplX3QgLi4uSW5kaWNlcz4KYXV0byBhcHBseShGICYmIGYsIEFyZ3NUdXBsZSAmJiBhcmdzLCBzdGQ6OmluZGV4X3NlcXVlbmNlPEluZGljZXMuLi4+KSB7CiAgIHJldHVybiBzdGQ6OmZvcndhcmQ8Rj4oZikoc3RkOjpnZXQ8SW5kaWNlcz4oc3RkOjpmb3J3YXJkPEFyZ3NUdXBsZT4oYXJncykpLi4uKTsKfQoKCnRlbXBsYXRlPGNsYXNzLi4uIEFyZ3M+IHZvaWQgZXhwYW5kKGNvbnN0IEFyZ3MmLi4uKSAKewogICAgdXNpbmcgdHVwbGVfdHlwZSA9IHN0ZDo6dHVwbGU8c3RkOjpyZW1vdmVfY3ZfdDxkZWNsdHlwZShwYXNzPEFyZ3M+KHN0ZDo6ZGVjbHZhbDxjb250ZXh0PigpKSk+Li4uPjsKCQogICAgY29udGV4dCBjdHg7CiAgICB0dXBsZV90eXBlIGFyZ3MgeyBwYXNzPEFyZ3M+KGN0eCkuLi4gfTsKICAgIAogICAgYXBwbHkoc29tZV9mdW5jdGlvbiwKICAgICAgICAgc3RkOjptb3ZlKGFyZ3MpLAogICAgICAgICBzdGQ6Om1ha2VfaW5kZXhfc2VxdWVuY2U8c2l6ZW9mLi4uKEFyZ3MpPiB7fSk7Cn0KIAppbnQgbWFpbigpCnsKICAgIGV4cGFuZCg0MiwgdHJ1ZSwgc3RkOjpzdHJpbmcgeyAiYW5zd2VyIiB9KTsKfQo=