template<typename T>
struct LinearForm
{
    T a, b;
    auto operator()(T const& x) const { return a*x+b; }
};

template<typename T> auto operator+( LinearForm<T> const& l1, LinearForm<T> const& l2 ){ return LinearForm<T>{ l1.a+l2.a, l1.b+l2.b }; }
template<typename T> auto operator+( T const& scl,            LinearForm<T> const& l2 ){ return LinearForm<T>{      l2.a, scl +l2.b }; }
template<typename T> auto operator+( LinearForm<T> const& l1, T const& scl            ){ return LinearForm<T>{ l1.a,      l1.b+scl  }; }

template<typename T> auto operator-( LinearForm<T> const& l1, LinearForm<T> const& l2 ){ return LinearForm<T>{ l1.a-l2.a, l1.b-l2.b }; }
template<typename T> auto operator-( T const& scl,            LinearForm<T> const& l2 ){ return LinearForm<T>{     -l2.a, scl -l2.b }; }
template<typename T> auto operator-( LinearForm<T> const& l1, T const& scl            ){ return LinearForm<T>{ l1.a,      l1.b-scl  }; }

template<typename T> auto operator*( T const& scl,            LinearForm<T> const& l2 ){ return LinearForm<T>{ scl*l2.a, scl*l2.b }; }
template<typename T> auto operator*( LinearForm<T> const& l1, T const& scl            ){ return LinearForm<T>{ l1.a*scl, l1.b*scl  }; }

template<typename T> auto operator/( LinearForm<T> const& l1, T const& scl            ){ return LinearForm<T>{ l1.a/scl, l1.b/scl  }; }

#include <iostream>

template<typename T>
std::ostream& operator<<( std::ostream& s, LinearForm<T> const& l)
{
    s << "(" << l.a <<" * x + " << l.b << ")";
    return s;
}

int main()
{
    LinearForm<double> a{2.0, 3.0};
    LinearForm<double> b{1.0, 5.0};
    double d1 = 1., d2 = 2., d3 = 3., d4 = 4.;

    auto c = a + b * d2;
    std::cout << c << " Evaluated at x=10.0: " << c(10.0) << std::endl;
}
