reference collapsing problem

The following code is self explanatory.
I use many container<arithmetic> structures as algebra vectors.
To be algebra vectors is_densevector<T>::value must be true (commented for simplicity).
The problem is the reference collapsing thing which use the C1&& = C1&& + C2&& instead of C1 = const C1& + const C2&.
Is there any suggestions?
Or something like this (ideally):
1
2
3
4
5
6
7
template<typename C1, typename C2>
C1//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C1>::type
&&operator+(C1 &&v1, C2 &&v2)
{
   if (is_rvalue(v1)) ....;
   else if (is_lvalue(v1)) ....;
}

Here the complete code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <array>
#include <vector>
using namespace std;


template<typename C1, typename C2> void add(C1 &v1, const C2 &v2) { cout << "add(v1,v2)" << endl;  }
template<typename C1, typename C2, typename C3> void add(C1 &v1, const C2 &v2, const C3 &v3) { cout << "add(v1,v2,v3)" << endl;  }

template<typename C1, typename C2>
C1//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C1>::type
&operator+=(C1 &v1, const C2 &v2) { cout << "v1 += v2 : "; add(v1, v2); return v1;  }

template<typename C1, typename C2>
C1//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C1>::type
operator+(const C1 &v1, const C2 &v2) { cout << "C1 = const C1& + const C2& : "; C1 r; add(r, v1, v2); return r; }
template<typename C1, typename C2>
C2//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C2>::type
&&operator+(const C1 &v1, C2 &&v2) { cout << "C2&& = const C1& + C2&& : "; return v2 += v1; }
template<typename C1, typename C2>
C1//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C1>::type
&&operator+(C1 &&v1, const C2 &v2) { cout << "C1&& = C2&& + const C2& : "; return v1 += v2; }
template<typename C1, typename C2>
C1//typename std::enable_if<is_densevector<C1>::value && is_densevector<C2>::value, C1>::type
&&operator+(C1 &&v1, C2 &&v2) { cout << "C1&& = C1&& + C2&& : "; return v1 += v2; }

int main()
{
	std::array<double,3> ar1{1,2,3};
	std::vector<int> ar2{3,2,1};
	ar1 + ar2;
	return 0;
}
Is it actually that important? In this case I'd say just allow the compiler to properly optimize the code.
Yes it is.
ar1 + ar2 must call C1 = const C1& + const C2& because ar1,ar2 are lvalues.
Calling the C1&& = C1&& + C2&& leads to destruction of ar1 so later it cannot be used.
If I want to not use ar1, I prefer to write: std::move(ar1) + ar2 (or ar1 += ar2)
And of-course move semantics in containers is a must.
Last edited on
Topic archived. No new replies allowed.