Q:

Using templated struct as constructor argument

I have a template class Point which will store x and y coordinates, data type of both can be any arithmetic type. 
template <typename T, typename U>
struct Point {
  T x;
  U y;
};

Line class takes two Points as constructor argument to find equation of line. 
class Line {
public:
  Line(Point p1, Point p2) {}
};

How can I design Line class so it can accept Point object of different data types? 
I have designed something like below, how can I improve it? 
template <class T, class U,
          class = typename std::enable_if<std::is_arithmetic<T>::value &&
                                          std::is_arithmetic<U>::value>::type>
struct Point
{
    T x;
    U y;
    typedef T x_type;
    typedef U y_type;
};

template <typename T1, 
          typename T2,
          typename P1 = typename T1::x_type,
          typename P2 = typename T1::y_type,
          typename P3 = typename T2::x_type,
          typename P4 = typename T2::y_type>
class Line {
public:
  Line(Point<P1, P2> p1, Point<P3, P4> p2) {}
};

The way I am planning to use is:
Point<int, long> p1 (2, 5);
Point<short, double> p2 (77, 33.5);
Line<Point<int, long>, Point<short, double>> line_(p1, p2);

OR

Line<Point<int, short>, Point<float, unsigned>> eq({1, 1}, {2.3f, 2});

What are the ways to to improvise or shorten the code. 

A:

You don't need to have so many type parameters in Line. 
template <typename Point> 
struct is_point : std::false_type {};

template <typename T, typename U>
struct is_point<Point<T, U>> : std::true_type {};

template <typename P1, typename P2>
class Line {
   static_assert(is_point<P1>::value && is_point<P2>::value, "Line needs Point template parameters")
   public:
   Line(P1 p1, P2 p2) {}
};

