Reputation: 768
I'm trying to convert a parameter pack into references, because some arguments to my function can be a mix of r-/l- values. The function in question:
//must return tuple
template <typename ...U>
std::tuple<U...> input(const char* format, U ...args) {
std::tuple<U...> t = std::tuple<U...> (args...);
//other code....
}
There is some test code that I can't touch... This will call my function:
template <typename... U>
std::tuple<U...> test_input(const char* fmt, U &&...inp) {
input(fmt, std::forward<U>(params)...);
//other stuff...
}
And 2 test objects (also untouchable) which have deleted copy/move constructors A()
and B()
. as in:
A(const A &) = delete; //same for B
A &operator=(const A &) = delete; //same for B
If I call the function, as is, I'll get "deleted copy-constructor" or "deleted constructor" errors. For example:
test_input("blah blah", 1, i, "a", std::string("a"), A(123) B("string"));
The problem is that it can be any mix of r-/l-values and I don't know how to convert them to all be references
I understand that I need a reference to the arguments. I've tried using std::forward
, std::forward_as_tuple
, std::make_tuple
, as well as changing the second parameter to input
to be U & ...args
and U &&...args
I also understand that I need to use reference collapsing:
I tried to use the first and third rules to convert anything to a type of A&
, but I still get errors such as: call to deleted constructor of 'B'
and expects an l-value for 2nd argument
In case my question wasn't clear - How do I convert args
, the second argument of input
, to a tuple of references?
Upvotes: 1
Views: 186
Reputation: 13988
I think you want to do something like this:
#include <tuple>
#include <string>
//must return tuple
template <typename ...U>
std::tuple<U&&...> input(const char*, U&&...args) {
return std::tuple<U&&...>(std::forward<U>(args)...);
//other code....
}
template <typename... U>
std::tuple<U&&...> test_input(const char* fmt, U &&...inp) {
return input(fmt, std::forward<U>(inp)...);
//other stuff...
}
struct A {
A(int) { }
A(const A &) = delete; //same for B
A &operator=(const A &) = delete; //same for B
};
struct B {
B(const char *) { }
B(const B &) = delete; //same for B
B &operator=(const B &) = delete; //same for B
};
int main() {
int i = 1;
test_input("blah blah", 1, i, "a", std::string("a"), A(123), B("string"));
}
Upvotes: 2