I am testing a universal link with the following code,
template <typename T> vector<T> attach_(vector<T> xs, T&& x) { xs.push_back(std::forward<T>(x)); return xs; } int main() { int k = 2; attach_(std::move(vector<int>{1,2,3}),k);
and received an error message:
no matching function for call to 'attach_(std::remove_reference<std::vector<int> >::type, int&)' attach_(std::move(vector<int>{1,2,3}),k); note: template argument deduction/substitution failed: note: deduced conflicting types for parameter 'T' ('int' and 'int&') attach_(std::move(vector<int>{1,2,3}),k);
SO has a question for a similar error. The error message "deduced inconsistent types for the 'const T' parameter" about const references.
I also checked several other cases, some with type conversions. Some work and others not.
I have heard that universal links like T&& fit all. Why is this happening here?
The second question is how to enter attach_ to make sure that the move semantics work for both xs and x for the corresponding input? Ultimately, I would like to have a variant of the following:
for(int i = 0; i < 100; i++) xs = attach_(xs,values[i])
work without having to make unnecessary copies.
(This is verified with gcc4.8.1 using g ++ -std = C ++ 11 test.cpp)
thanks
- EDIT ---
Thanks everyone for the great answers.
So now I understand that for this case itβs useful to just use pass-by-value and move T He believes that the xs vector is not copied unnecessarily when passing parameters and going back if it is used in a loop, right?
I asked a related question When is a const reference better than pass-by-value in C ++ 11? . There I had this example where everyone said pass-by-vale is a bad idea:
int hd(vector<int> a) { return a[0]; }
Is it even possible to use a universal link to handle both the hd case and the attach_ case in this message to avoid unnecessary copies?
Thanks again.
--- EDIT2 ---
So, I tested the versions in the answers plus the const reference below. Optimization is not used to identify any potential problems. The ref const version is the worst since it forces you to copy. Everything else has the same speed if std::move(a) used for the vector, except for raw push_call calls faster. I think optimization can eliminate this difference. I think the test (or maybe the int type) is not big enough to show the difference between push_back(x) and push_back(std::move(x))
#include <vector> #include <iostream> #include <chrono> using namespace std; template <class T> vector<T> attach(vector<T> v, T x) { v.push_back(x); return v; } template <typename T> vector<T> attach1(vector<T> xs, T x) { xs.push_back(std::move(x)); return xs; } template <typename T, typename E = typename std::remove_reference<T>::type> std::vector<E> attach2(std::vector<E> xs, T&& x) { xs.push_back(std::forward<T>(x)); return xs; } template <typename C, typename T> C attach3(C&& xs, T&& x) { xs.push_back(std::move<T>(x)); return std::forward<C>(xs); } template <class T> vector<T> attach4(const vector<T>& v, T x) { vector<T> ret = v; ret.push_back(x); return std::move(ret); } using namespace std::chrono; int main() { int N = 100000; vector<int> a; auto time = high_resolution_clock::now(); for (int i = 0; i < N; i++) { //a.push_back(i); //0s //a = attach(a,i); //15s //a = attach(std::move(a),i); //0.03s //a = attach2(std::move(a),i); //0.03s a = attach3(std::move(a),i); //0.03s //a = attach4(std::move(a),i); //14.9s } cout << duration_cast<duration<double>>(high_resolution_clock::now() - time).count() << endl; }