#include <tuple>
#include <iostream>
// sequence
template<size_t...>
struct Sequence
{ };
template<size_t N, size_t... Seq>
struct GenerateSequence : GenerateSequence<N - 1, N - 1, Seq...>
{ };
template<size_t... Seq>
struct GenerateSequence<0, Seq...>
{
using type = Sequence<Seq...>;
};
// invoke tuple
struct TupleForEachInvoker
{
template<typename Func, typename ForEachFunc, typename Tuple, size_t... Seq>
static auto invoke(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple, Sequence<Seq...>)
-> decltype(func(forEachFunc(std::get<Seq>(std::forward<Tuple>(tuple)))...))
{
return func(forEachFunc(std::get<Seq>(std::forward<Tuple>(tuple)))...);
}
template<typename Func, typename ForEachFunc, typename... Args>
static auto apply(Func&& func, ForEachFunc&& forEachFunc, std::tuple<Args...>&& args)
-> decltype(invoke(std::forward<Func>(func),
std::forward<ForEachFunc>(forEachFunc),
std::forward<std::tuple<Args...>>(args),
typename GenerateSequence<sizeof...(Args)>::type()))
{
return invoke(std::forward<Func>(func),
std::forward<ForEachFunc>(forEachFunc),
std::forward<std::tuple<Args...>>(args),
typename GenerateSequence<sizeof...(Args)>::type());
}
};
template<typename Func, typename ForEachFunc, typename Tuple>
inline auto invokeWithMemberFromAll(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple)
-> decltype(TupleForEachInvoker::apply(std::forward<Func>(func),
std::forward<ForEachFunc>(forEachFunc),
std::forward<Tuple>(tuple)))
{
return TupleForEachInvoker::apply(std::forward<Func>(func),
std::forward<ForEachFunc>(forEachFunc),
std::forward<Tuple>(tuple));
}
// exemplar
template<typename T>
struct Foo
{
T& data() { return _val; }
T _val;
};
struct Extract
{
template<typename T>
T& operator() (Foo<T>& f) { return f.data(); }
};
int main()
{
Foo<int> i { 5 };
Foo<double> d { 6. };
Foo<const char*> s { "hello world" };
auto cb = [](int& i, const double& d, const char* s)
{
std::cout << "i=" << i << ", d=" << d << ", s=" << s << std::endl;
i += 2;
};
// rvalue reference to tuple
invokeWithMemberFromAll(cb, Extract{}, std::tie(i, d, s));
std::cout << i.data() << std::endl;
// lvalue reference to tuple - fails
auto tuple = std::tie(i, d, s);
invokeWithMemberFromAll(cb, Extract{}, tuple);
std::cout << i.data() << std::endl;
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8aW9zdHJlYW0+CgovLyBzZXF1ZW5jZQoKdGVtcGxhdGU8c2l6ZV90Li4uPgpzdHJ1Y3QgU2VxdWVuY2UKeyB9OwoKdGVtcGxhdGU8c2l6ZV90IE4sIHNpemVfdC4uLiBTZXE+CnN0cnVjdCBHZW5lcmF0ZVNlcXVlbmNlIDogR2VuZXJhdGVTZXF1ZW5jZTxOIC0gMSwgTiAtIDEsIFNlcS4uLj4KeyB9OwoKdGVtcGxhdGU8c2l6ZV90Li4uIFNlcT4Kc3RydWN0IEdlbmVyYXRlU2VxdWVuY2U8MCwgU2VxLi4uPgp7Cgl1c2luZyB0eXBlID0gU2VxdWVuY2U8U2VxLi4uPjsKfTsKCi8vIGludm9rZSB0dXBsZQoKc3RydWN0IFR1cGxlRm9yRWFjaEludm9rZXIKewoJdGVtcGxhdGU8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUgRm9yRWFjaEZ1bmMsIHR5cGVuYW1lIFR1cGxlLCBzaXplX3QuLi4gU2VxPgoJc3RhdGljIGF1dG8gaW52b2tlKEZ1bmMmJiBmdW5jLCBGb3JFYWNoRnVuYyYmIGZvckVhY2hGdW5jLCBUdXBsZSYmIHR1cGxlLCBTZXF1ZW5jZTxTZXEuLi4+KQoJCS0+IGRlY2x0eXBlKGZ1bmMoZm9yRWFjaEZ1bmMoc3RkOjpnZXQ8U2VxPihzdGQ6OmZvcndhcmQ8VHVwbGU+KHR1cGxlKSkpLi4uKSkKCXsKCQlyZXR1cm4gZnVuYyhmb3JFYWNoRnVuYyhzdGQ6OmdldDxTZXE+KHN0ZDo6Zm9yd2FyZDxUdXBsZT4odHVwbGUpKSkuLi4pOwoJfQoKCXRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lIEZvckVhY2hGdW5jLCB0eXBlbmFtZS4uLiBBcmdzPgoJc3RhdGljIGF1dG8gYXBwbHkoRnVuYyYmIGZ1bmMsIEZvckVhY2hGdW5jJiYgZm9yRWFjaEZ1bmMsIHN0ZDo6dHVwbGU8QXJncy4uLj4mJiBhcmdzKQoJCS0+IGRlY2x0eXBlKGludm9rZShzdGQ6OmZvcndhcmQ8RnVuYz4oZnVuYyksCgkJCQkJCSAgIHN0ZDo6Zm9yd2FyZDxGb3JFYWNoRnVuYz4oZm9yRWFjaEZ1bmMpLAoJCQkJCQkgICBzdGQ6OmZvcndhcmQ8c3RkOjp0dXBsZTxBcmdzLi4uPj4oYXJncyksCgkJCQkJCSAgIHR5cGVuYW1lIEdlbmVyYXRlU2VxdWVuY2U8c2l6ZW9mLi4uKEFyZ3MpPjo6dHlwZSgpKSkKCXsKCQlyZXR1cm4gaW52b2tlKHN0ZDo6Zm9yd2FyZDxGdW5jPihmdW5jKSwKCQkJCQkgIHN0ZDo6Zm9yd2FyZDxGb3JFYWNoRnVuYz4oZm9yRWFjaEZ1bmMpLAoJCQkJCSAgc3RkOjpmb3J3YXJkPHN0ZDo6dHVwbGU8QXJncy4uLj4+KGFyZ3MpLAoJCQkJCSAgdHlwZW5hbWUgR2VuZXJhdGVTZXF1ZW5jZTxzaXplb2YuLi4oQXJncyk+Ojp0eXBlKCkpOwoJfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUgRm9yRWFjaEZ1bmMsIHR5cGVuYW1lIFR1cGxlPgppbmxpbmUgYXV0byBpbnZva2VXaXRoTWVtYmVyRnJvbUFsbChGdW5jJiYgZnVuYywgRm9yRWFjaEZ1bmMmJiBmb3JFYWNoRnVuYywgVHVwbGUmJiB0dXBsZSkKICAgIC0+IGRlY2x0eXBlKFR1cGxlRm9yRWFjaEludm9rZXI6OmFwcGx5KHN0ZDo6Zm9yd2FyZDxGdW5jPihmdW5jKSwKICAgIAkJCQkJCQkJCSAgIHN0ZDo6Zm9yd2FyZDxGb3JFYWNoRnVuYz4oZm9yRWFjaEZ1bmMpLAogICAgCQkJCQkJCQkJICAgc3RkOjpmb3J3YXJkPFR1cGxlPih0dXBsZSkpKQp7CiAgICByZXR1cm4gVHVwbGVGb3JFYWNoSW52b2tlcjo6YXBwbHkoc3RkOjpmb3J3YXJkPEZ1bmM+KGZ1bmMpLAogICAgCQkJCQkJCQkgIHN0ZDo6Zm9yd2FyZDxGb3JFYWNoRnVuYz4oZm9yRWFjaEZ1bmMpLAogICAgCQkJCQkJCQkgIHN0ZDo6Zm9yd2FyZDxUdXBsZT4odHVwbGUpKTsKfQoKLy8gZXhlbXBsYXIKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBGb28KewogICAgVCYgZGF0YSgpIHsgcmV0dXJuIF92YWw7IH0KCVQgX3ZhbDsKfTsKCnN0cnVjdCBFeHRyYWN0CnsKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+CiAgICBUJiBvcGVyYXRvcigpIChGb288VD4mIGYpIHsgcmV0dXJuIGYuZGF0YSgpOyB9Cn07CgppbnQgbWFpbigpCnsKCUZvbzxpbnQ+ICAgICAgICAgaSB7IDUgfTsKCUZvbzxkb3VibGU+ICAgICAgZCB7IDYuIH07CglGb288Y29uc3QgY2hhcio+IHMgeyAiaGVsbG8gd29ybGQiIH07CgoJYXV0byBjYiA9IFtdKGludCYgaSwgY29uc3QgZG91YmxlJiBkLCBjb25zdCBjaGFyKiBzKQoJCXsKCQkJc3RkOjpjb3V0IDw8ICJpPSIgPDwgaSA8PCAiLCBkPSIgPDwgZCA8PCAiLCBzPSIgPDwgcyA8PCBzdGQ6OmVuZGw7CgkJCQoJCQlpICs9IDI7CgkJfTsKCgoJLy8gcnZhbHVlIHJlZmVyZW5jZSB0byB0dXBsZQoJaW52b2tlV2l0aE1lbWJlckZyb21BbGwoY2IsIEV4dHJhY3R7fSwgc3RkOjp0aWUoaSwgZCwgcykpOwoKICAgIHN0ZDo6Y291dCA8PCBpLmRhdGEoKSA8PCBzdGQ6OmVuZGw7CgoJLy8gbHZhbHVlIHJlZmVyZW5jZSB0byB0dXBsZSAtIGZhaWxzCglhdXRvIHR1cGxlID0gc3RkOjp0aWUoaSwgZCwgcyk7CglpbnZva2VXaXRoTWVtYmVyRnJvbUFsbChjYiwgRXh0cmFjdHt9LCB0dXBsZSk7CgkKICAgIHN0ZDo6Y291dCA8PCBpLmRhdGEoKSA8PCBzdGQ6OmVuZGw7Cgp9Cg==
prog.cpp: In function 'int main()':
prog.cpp:92:46: error: no matching function for call to 'invokeWithMemberFromAll(main()::<lambda(int&, const double&, const char*)>&, Extract, std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&)'
invokeWithMemberFromAll(cb, Extract{}, tuple);
^
prog.cpp:92:46: note: candidate is:
prog.cpp:46:13: note: template<class Func, class ForEachFunc, class Tuple> decltype (TupleForEachInvoker::apply(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<Tuple>(tuple))) invokeWithMemberFromAll(Func&&, ForEachFunc&&, Tuple&&)
inline auto invokeWithMemberFromAll(Func&& func, ForEachFunc&& forEachFunc, Tuple&& tuple)
^
prog.cpp:46:13: note: template argument deduction/substitution failed:
prog.cpp: In substitution of 'template<class Func, class ForEachFunc, class Tuple> decltype (TupleForEachInvoker::apply(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<Tuple>(tuple))) invokeWithMemberFromAll(Func&&, ForEachFunc&&, Tuple&&) [with Func = main()::<lambda(int&, const double&, const char*)>&; ForEachFunc = Extract; Tuple = std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&]':
prog.cpp:92:46: required from here
prog.cpp:49:43: error: cannot bind 'std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>' lvalue to 'std::tuple<Foo<int>&, Foo<double>&, Foo<const char*>&>&&'
std::forward<Tuple>(tuple)))
^
prog.cpp:32:14: note: initializing argument 3 of 'static decltype (TupleForEachInvoker::invoke(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<std::tuple<_Tail ...> >(args), typename GenerateSequence<sizeof... (Args)>::type())) TupleForEachInvoker::apply(Func&&, ForEachFunc&&, std::tuple<_Tail ...>&&) [with Func = main()::<lambda(int&, const double&, const char*)>&; ForEachFunc = Extract; Args = {Foo<int>&, Foo<double>&, Foo<const char*>&}; decltype (TupleForEachInvoker::invoke(forward<Func>(func), forward<ForEachFunc>(forEachFunc), forward<std::tuple<_Tail ...> >(args), typename GenerateSequence<sizeof... (Args)>::type())) = void; typename GenerateSequence<sizeof... (Args)>::type = Sequence<0u, 1u, 2u>]'
static auto apply(Func&& func, ForEachFunc&& forEachFunc, std::tuple<Args...>&& args)
^