gpt4 book ai didi

C++:为用户定义的类型进行转换

转载 作者:行者123 更新时间:2023-11-30 04:40:21 26 4
gpt4 key购买 nike

如何获得与内置用户定义类型相同的转换处理,例如:

float a = 5.4;
std::string s = a;//error, no conversion avaible
int x = a;//warning, possible data loss
int y = (int)a;//fine
int z = static_cast<int>a;//fine
float b = c;//warning, possible data loss

现在假设我有自己的 Int 和 Float 类,我如何才能得到相同的错误和警告?

class Int
{
public:
int value;
Int(int v);
...
};
class Float
{
public:
float value;
Float(float v);
...
};
Int c = 10;
Float a = 5.5;
std::string s = a;
Int x = a;
Int y = (Int)a;
Int z = static_cast<Int>a;
Float b = c;

我知道创建重载转换运算符和使用构造函数,但是我不知道如何使它正确地用于隐式和显式转换,例如考虑。如果我不在这些方法中添加显式强制转换,那么我会在编译时收到警告,但在调用它们时不会收到警告,如果我这样做了,那么我在类代码中不会收到错误,但我仍然没有收到使用时发出警告。

我猜想有一些方法可以将转换运算符标记为显式,这样如果它尝试隐式转换而不是显式(C 风格或 static_cast)转换,则会生成警告)

编辑:好吧,我想我在这种情况下得到了它,在这种情况下,所有相关类型都是完全已知的,但是当一个或两个都是模板,并且两种类型都映射到内置类型时呢?

template<typename T> class Vector2
{
public:
T x, y;
Vector2():x(0),y(0){}
Vector2(T x, T y):x(x),y(y){}

//Works as expected, warning if adding T and T2 is unsafe, or error if
//incompatible*/
template<typename T2>Vector2<T>& operator += (const Vector2<T2> &v);
//Also works as desired
Vector2<T>& operator *= (T s);

//allows the conversion, but always generates warnings if
//T and T2 would, even if this constructor is used by an explicit
//case. How can I suppress the warnings for the explicit cast, but
//not for implicit casts?
template<typename T2>Vector2(const Vector2<T2> &v);//uses implicit conversion form T2 to T
};

从 say Vector2 到 Vector2 的隐式转换按预期工作,但是从 say Vector2 到 Vector2 的转换总是导致(2,一个用于 x,一个用于 y)警告,即使使用了显式 C 样式或 static_cast 也是如此。我想保留隐式转换的警告,而不是显式转换。

我知道我可以解决这个问题,创建一个特殊的 T vector_cast(T2) 类型方法,在内部对每个元素使用显式转换,但我宁愿能够使用 C 风格和 static_casts

最佳答案

我也觉得没有办法。我能做到的最好结果是您想要生成警告的行根本不会编译。

class Int
{
public:
int value;
Int(int v);
};

class Float
{
public:
float value;
Float(float v);
operator int() { return static_cast<int>(value); }
};

int main()
{
Float a = 5.5;
//Int x = a; //no warning, simply doesn't compile
Int y = (int)a;
Int z = static_cast<int>(a);
}

编辑:关于您关于 Vector2 的问题

要做的一件事可能是禁用不同 Vector2 类型之间的所有隐式转换。作为捷径,您可以提供一个 vector_cast 以允许显式转换:

template <class T, class S>
Vector2<T> vector_cast(const Vector2<S>& s)
{
return Vector2<T>(static_cast<T>(s.x), static_cast<T>(s.y));
}

另一件事可能是引入一些模板元编程,以启用转换构造函数以进行安全转换。

在我看来,boost 不包含这样的 type_trait,因此我推出了自己的。

有点简化:Target 必须至少与 Source 一样大,如果 Source 是 float ,Target 不能是整数。然而,它忽略了符号问题,以及浮点类型是否可以表示整数类型的完整范围的问题(例如,float 不能精确存储所有 32 位 int,但 double 可以)。

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>

template <class S, class T>
struct is_safe_conversion:
boost::integral_constant<
bool,
(sizeof(S) <= sizeof(T)) && !(boost::is_floating_point<S>::value && boost::is_integral<T>::value)
>
{
};

template<typename T> class Vector2
{
public:
T x, y;
Vector2():x(0),y(0){}
Vector2(T x, T y):x(x),y(y){}

template <class U>
Vector2(const Vector2<U>& other, typename boost::enable_if<is_safe_conversion<U, T> >::type* = 0):
x(other.x), y(other.y) {}

};

template <class T, class S>
Vector2<T> vector_cast(const Vector2<S>& s)
{
return Vector2<T>(static_cast<T>(s.x), static_cast<T>(s.y));
}

int main()
{
Vector2<double> vd, vd2;
Vector2<int> vi, vi2;
Vector2<float> vf, vf2;

vd = vd2;
vd = vi;
vd = vf;

//vi = vd; //error
vi = vector_cast<int>(vd);
vi = vi2;
//vi = vf; //error
vi = vector_cast<int>(vf); //explicit

//vf = vd; //error
vf = vector_cast<float>(vd);

//following compiles, but produces a warning (float cannot represent all integers)
//TODO: enhance is_safe_conversion!
vf = vi;
vf = vf2;
}

关于C++:为用户定义的类型进行转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1528292/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com