It seems to be simple and short, but does this method have any hidden overhead versus classic solutions with template specialization and helper functions/classes?
It has a drawback that could be annoying in some cases. If your type has reference qualifiers on member methods, you can encounter problems by getting an lvalue reference out of it.
Let's consider the following example:
#include<utility> #include<tuple> struct S { void foo() && {} }; template<typename T> void f(T &&t) { std::forward<T>(t).foo(); } int main() { f(S{}); }
Everything works fine for we have originally an rvalue reference and by forwarding the forwarding reference we can safely call the foo member method.
Let's consider now your snippet (note, the following code doesn't compile - continue reading):
#include<utility> #include<tuple> struct S { void foo() && {} }; template<typename... T> void g(T&&... t) { auto &last = std::get<sizeof...(T) - 1 >(std::tie(t...)); last.foo(); } int main() { g(S{}); }
This won't compile for foo cannot be invoked anymore on a variable having type S & because of the reference qualifier.
On the other side, by forwarding and extracting the last parameter somehow you can keep intact its type and you don't have such a problem.
As an example:
template<typename... T> void g(T&&... t) { std::get<sizeof...(T) - 1>(std::forward_as_tuple(std::forward<T>(t)...)).foo(); }
std::getorstd::tuple_elementdoes equivalent things with template specialization. The potential downside is that you instantiatestd::tuple<Arg&...>andstd::getinstead of potentially less template instantiation of provided solution.sizeofand howstd::tuple(std::tie) is implemented. I guess this is more efficient simply because it instantiates less auxiliary types. However, there maybe very inefficient implementations ofstd::tuplethat at the end is the same as other solutions (e.g.std::tupleis implemented recursively). In conclusion, I think is efficient, but the hidden cost is instd::tuple.sizeofshould provide compile time constant, there should be no overhead, am I wrong? I would worry more aboutstd::tupleand that is the question could be there runtime overhead for that.std::tuple. So the answer is really sensitive to howstd::tupleis implemented. If it uses recursion it may be similar to other solutions. Your implementation looks easy because you are just exploiting the fact that someone else implementedstd::tuple.