给定一个简单的模板< 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)
我相信为了实现这个目标,我需要实现这两个,一个隐含的和一个显式的转换构造函数,类型为U.但是,不可能重载“隐式”和显式:
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; };
我怎么可以实现这个目标(我想我不能…)
我最初的想法是,我需要启用/禁用一个或另一个取决于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);
简而言之,如果std :: is_convertible< U,T> :: value == true,并且如果U x; T y = x;不会发出关于信息丢失的编译器警告.
解决方法
您不能在显式上重载,但您可以提供一个显式转换构造函数和隐式转换运算符:
#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; }
输出:
explicit implicit
用gcc和clang测试.