template<typename T> class Group;
template<typename...U>
class Group<std::tuple<U...>> {
public:
typedef std::tuple<U...> type;
void emplace_back(U&...elem) {
data_.emplace_back(elem...);
}
void emplace_back(U&&...elem) {
data_.emplace_back(elem...);
}
private:
std::vector<type> data_;
};
int main() {
Group<std::tuple<int, std::string>> g;
int e1 = 10;
std::string e2 = "elem2";
g.emplace_back(e1, e2); //OK
g.emplace_back(e1, "elem2"); //error, no instance of overloaded function
return 0;
}
I need to create a template class that, in its partial specialization, uses a std::tuple
to create a type list consisting of non-cvr (non-const, non-volatile, non-reference) ordinary types. The class should use a std::vector
to store a series of elements of std::tuple
type, where the element types in the std::tuple
match the created type list. The example code has abstracted and simplified the problem, so the operation of creating a type list using std::tuple
might seem nonsense.
When inserting elements into the std::vector
, a non-template member function calls the std::vector::emplace_back()
function. Since it's a non-template function, perfect forwarding of arguments cannot be achieved; either all arguments in the parameter pack are uniformly passed as lvalue references, or they are uniformly passed as rvalue references.
Now, I am wondering if there is a way to individually determine whether each argument is an lvalue reference or an rvalue reference and forward them accordingly to the std::vector::emplace_back()
function.
I thought of changing Group::emplace_back()
to a template function, which would allow perfect forwarding. However, this would lose the constraint of the class template's type parameter U
on the function's arguments, so I prefer not to use this method.
std::string
not aconst char*
for "elem2" and that is what your compiler is trying to tell you. (Can be solved at callsite : use string literals and"elem2"s
).std::string("elem2")
, it will not find a matching function either.