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

   namespace named_operator {
      template<class D>struct make_operator{make_operator(){}};

      template<class T, char, class O> struct half_apply { T&& lhs; };

      template<class Lhs, class Op>
      half_apply<Lhs, '+', Op> operator+( Lhs&& lhs, make_operator<Op> ) {
        return {std::forward<Lhs>(lhs)};
      }

      template<class Lhs, class Op, class Rhs>
      auto operator+( half_apply<Lhs, '+', Op>&& lhs, Rhs&& rhs )
      -> decltype( named_invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) ) )
      {
        return named_invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) );
      }
    }

    namespace ops {
      struct concat_t:named_operator::make_operator<concat_t>{};
      static const concat_t concat{};
      template<class T, class A, class A2>
      std::vector<T,A> named_invoke( std::vector<T,A> lhs, concat_t, std::vector<T,A2> const& rhs){
        lhs.insert(lhs.end(), rhs.begin(), rhs.end());
        return std::move(lhs);
      }
    }
    using ops::concat;

    int main(){
       std::vector<int> a{1,2,3};
       std::vector<int> b{7,8,9};

      for( auto x: a +concat+ a +concat+ b )
        std::cout <<x<<'\n';
    }