#include <iostream>
#include <vector>
#include <utility>

    template<typename T, typename U, typename A1, typename A2>
    decltype(std::declval<T>() * std::declval<U>() + std::declval<T>() * std::declval<U>())
    dot_product( std::vector<T, A1> const& lhs, std::vector<U, A2> const& rhs )
    {
      decltype(std::declval<T>() * std::declval<U>() + std::declval<T>() * std::declval<U>()) sum = 0;
      for( std::size_t i = 0; i < lhs.size() && i < rhs.size(); ++i ) {
      	sum += lhs[i] * rhs[i];
      }
      return sum;
    }
    template<typename LHS>
    struct half_dot {
      LHS lhs;
      half_dot( LHS&& lhs_ ):lhs(std::forward<LHS>(lhs_)) {}
      template<typename RHS>
      decltype( dot_product( std::declval<LHS>(), std::declval<RHS>() ) )
      operator*( RHS&& rhs ) const {
        return dot_product( std::forward<LHS>(lhs), std::forward<RHS>(rhs) );
      }
    };
    struct dot_t {};
    template<typename LHS>
    half_dot<LHS> operator*( LHS&& lhs, dot_t ) {
      return {std::forward<LHS>(lhs)};
    }
    static dot_t dot;
      
    int main() {
      std::vector<int> foo = {1,2,3};
      std::vector<int> bar = {3,2,1};
      std::cout << (foo *dot* bar) << "\n";
    }