I've been reading Item 6 from Scott Meyers' Effective Modern C++ and noticed that he mentioned a technique called expression templates. I've decided to give it a try and implemented a vector that supports addition and subtraction:
#include <iostream>
#include <vector>
template<typename T>
class Vec
{
public:
std::vector<T> data;
typedef typename std::vector<T>::size_type size_type;
Vec(size_type size): data(size)
{
}
Vec(const std::initializer_list<T>& elements): data(elements.size())
{
size_type i = 0;
for (const auto& el: elements)
{
data[i++] = el;
}
}
template<typename VecOperation>
Vec(const VecOperation& vo): data(vo.t2.data.size())
{
for (size_type i = 0; i < data.size(); ++i)
{
data[i] = vo[i];
}
}
T operator[](size_type i) const
{
return data[i];
}
};
template<typename T1, typename T2>
struct VecSum
{
const T1& t1;
const T2& t2;
auto operator[](typename T2::size_type i) const
{
return t1[i] + t2[i];
}
};
template<typename T1, typename T2>
struct VecDiff
{
const T1& t1;
const T2& t2;
auto operator[](typename T2::size_type i) const
{
return t1[i] - t2[i];
}
};
template<typename T1, typename T2>
auto operator+(const T1& t1, const T2& t2)
{
return VecSum<T1, T2>{t1, t2};
}
template<typename T1, typename T2>
auto operator-(const T1& t1, const T2& t2)
{
return VecDiff<T1, T2>{t1, t2};
}
int main()
{
Vec<int> v1{1, 2, 3, 4, 5};
Vec<int> v2{6, 7, 8, 9, 11};
Vec<int> v3{3, 5, 2, 0, 17};
Vec<int> v4 = v1+v2-v3;
for (const auto& x: v4.data)
{
std::cout << x << ", ";
}
std::cout << std::endl;
return 0;
}
The main advantage of this solution is that in the line Vec<int> v4 = v1+v2-v3;
no additional temporaries of type Vec are created, which increases performance.
I'd be grateful if someone could point potential drawbacks and possible improvements of this code.