如何为同一类型提供隐式和显式转换ctr?

Dan*_*ger 10 c++ templates type-conversion c++11

鉴于一个简单的template <typename T> struct X { T x, y; };,我想提供转换构造函数,以便用户可以编写:

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)
Run Code Online (Sandbox Code Playgroud)

我相信为了实现这个目标,我需要从类型实现隐式和显式转换构造函数U.但是不可能在"隐含"上重载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;
};
Run Code Online (Sandbox Code Playgroud)

我怎么能实现这个目标(我想我不能......)?

我最初的想法是,我需要启用/禁用一个或另一个取决于is_lossless_convertible.那么有合适的类型特征吗?

我想测试标量类型U是否可以转换为类型T而不会损失精度:

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);
Run Code Online (Sandbox Code Playgroud)

简而言之,它应该产生true是否std::is_convertible<U, T>::value == true 以及如果U x; T y = x;不发出关于信息丢失的编译器警告.

eca*_*mur 6

您不能重载显式,但您可以提供显式转换构造函数和隐式转换运算符:

#include <iostream>
template<typename T> struct S {
   S() {}
   template<typename U> explicit S(const S<U> &) { std::cout << "explicit\n"; }
   template<typename U> operator S<U>() { return S<U>(this); }
private:
   template<typename U> friend struct S;
   template<typename U> S(const S<U> *) { std::cout << "implicit\n"; }
};

int main() {
   S<double> sd;
   S<int> si1(sd);
   S<int> si2 = sd;
}
Run Code Online (Sandbox Code Playgroud)

输出:

explicit
implicit
Run Code Online (Sandbox Code Playgroud)

用gcc和clang测试.

显式转换构造优选的是隐式转换运算符,因为在后者的情况下有一个附加的(可能消隐)调用的拷贝构造S<int>.