Summary: I want to end up with a function that deduces the exact types it was called with and takes (e.g.) a tuple that forwards them (the types of which will be different from the exact types the function was called with).
I'm stuck trying to "know" via deduction the types of the arguments to a given function, whilst simultaneously forwarding them. I think I might be missing something crucial about how this works.
#include <tuple>
#include <string>
#include <functional>
template <typename ...Args>
struct unresolved_linker_to_print_the_type {
unresolved_linker_to_print_the_type();
};
void f(int,double,void*,std::string&,const char*) {
}
template <typename F, typename ...Args>
void g1(F func, Args&&... args) {
unresolved_linker_to_print_the_type<Args...>();
auto tuple = std::forward_as_tuple(args...);
unresolved_linker_to_print_the_type<decltype(tuple)>();
}
template <typename F, typename T, typename ...Args>
void g2(F func, const T& tuple, Args... args) {
unresolved_linker_to_print_the_type<Args...>();
unresolved_linker_to_print_the_type<decltype(tuple)>();
}
int main() {
int i;
double d;
void *ptr;
std::string str;
std::string& sref = str;
const char *cstr = "HI";
g1(f, i,d,ptr,sref,cstr);
g2(f, std::forward_as_tuple(i,d,ptr,sref,cstr), i,d,ptr,sref,cstr);
}
What I'd like to see is a scenario where when my function (e.g. g1
or g2
) gets called it knows and can use both the original types - int,double,void*,std::string&,const char*
and the forwarded arugments too.
In this instance I don't seem to be able to find this information from within g1
or g2
. The (deliberate, to print out the types) linker error shows me in g1
they are:
int&, double&, void*&, std::string&, char const*&
int&, double&, void*&, std::string&, char const*&
and in g2
:
int, double, void*, std::string, char const*
int&, double&, void*&, std::string&, char const*&
There are two thing I don't get here:
Why do none of the printed (via the linker error) types match what I actually passed in? (
int,double,void*,std::string&,const char
). Can I deduce what I actually was passed? Preferably with "natural" syntax, i.e. everything just once and nothing explicitly written out. I can explicitly write:g2<decltype(&f),decltype(std::forward_as_tuple(i,d,ptr,sref,cstr)),int,double,void*,std::string&,const char*>(f,std::forward_as_tuple(i,d,ptr,sref,cstr),i,d,ptr,sref,cstr);
but that's "unwieldy" to say the least!
In
g1
the presence of&&
in the function signature declaration seems to alter the types in the template parameterArgs
itself. Compare that with:template <typename T> void test(T t);
Or:
template <typename T> void test(T& t);
using either of those with:
int i; test(i);
doesn't change the type of
T
. Why does the&&
change the type ofT
itself when&
doesn't?