给定一个简单的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)
我相信为了实现这个目标,我需要实现类型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;
};
我怎样才能达到这个目标(我想我不能......)?
我最初的想法是我需要根据 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);
简而言之,如果true
,则std::is_convertible<U, T>::value == true
会产生U x; T y = x;
,如果{{1}}不会发出关于丢失的编译器警告,则信息。击>
答案 0 :(得分: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;
}
输出:
explicit
implicit
使用gcc和clang进行测试。
显式转换构造函数优先于隐式转换运算符,因为在后一种情况下,对S<int>
的复制构造函数进行了额外的(可能是省略的)调用。