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.