#include #include #include template class Vector_Base { public: auto operator[](std::size_t i) const; }; template auto Vector_Base::operator[](std::size_t i) const { return static_cast(*this)[i]; } template class Vector : public Vector_Base> { public: template Vector(Vector_Base const& other) { for (std::size_t i{0}; i < dim; ++i) { data[i] = other[i]; } } Vector(std::initializer_list list) { std::copy(list.begin(), list.end(), data.begin()); } T operator[](std::size_t i) const { return data[i]; } T& operator[](std::size_t i) { return data[i]; } private: std::array data { }; }; template class Vector_Sum : public Vector_Base> { public: Vector_Sum(Vector_Base const& lhs, Vector_Base const& rhs) : lhs{lhs}, rhs{rhs} { } auto operator[](std::size_t i) const { return lhs[i] + rhs[i]; } private: Vector_Base const& lhs; Vector_Base const& rhs; }; template Vector_Sum operator+(Vector_Base const& lhs, Vector_Base const& rhs) { return { lhs, rhs }; } // Notice that RHS is not a vector but a scalar template class Vector_Product : public Vector_Base> { public: Vector_Product(Vector_Base const& lhs, RHS const& rhs) : lhs{lhs}, rhs{rhs} { } auto operator[](std::size_t i) const { return lhs[i] * rhs; } private: Vector_Base const& lhs; RHS const& rhs; }; // vector * scalar template Vector_Product operator*(Vector_Base const& lhs, RHS const& rhs) { return { lhs, rhs }; } // scalar * vector template Vector_Product operator*(LHS const& lhs, Vector_Base const& rhs) { return { rhs, lhs }; } int main() { using Vec = Vector; Vec a { 1, 2 }; Vec b { 3, 4 }; Vec c { 5, 6 }; Vec d { 0.5 * ((a + b) * 2.0 + c) }; }