Given a simple template <typename T> struct X { T x, y; };, I want to provide conversion constructors such that user can write:

X<double> a;
X<int16_t> b = a; // uses implicit conversion ctr (compiles with warning)
X<int16_t> c(a);  // uses explicit conversion ctr (compiles w/o warning)
X<int32_t> d = c; // uses implicit conversion ctr (compiles w/o warning)

I believe that to achieve this goal, I need to implement both, an implicit and an explicit conversion constructor from type U. But it's not possible to overload on "implicit" and explicit:

template <typename T> struct X {
     X(T x = T(), T y = T()) : x(x), y(y) {}

     // implicit conversion
     template <typename U> 
     X(const X<U>& other) : x(other.x), y(other.y) {}

     // not possible!
     template <typename U> 
     explicit X(const X<U>& other)
         : x(static_cast<T>(other.x))
         , y(static_cast<T>(other.y)) 
     {}

     T x, y;
};

How could I achieve this goal (I guess I can't...)?

My initial thought was that I need to enable/disable the one or other depending on is_lossless_convertible. So is there a suitable type trait?

I would like to test if a scalar type U is convertible to type T without loss of precision:

using namespace std;
static_assert(is_lossless_convertible<int16_t, int32_t>::value == true);
static_assert(is_lossless_convertible<int32_t, int16_t>::value == false);
static_assert(is_lossless_convertible<int16_t, uint32_t>::value == false);
static_assert(is_lossless_convertible<int32_t, double>::value == true);
static_assert(is_lossless_convertible<double, int32_t>::value == false);

In short, it should yield true if std::is_convertibl

Edit
Report