C++:铸造为用户定义类型
我怎样才能铸造为用户定义类型相同HANDELING内置的,如:C++:铸造为用户定义类型
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
};
比如从Vector2到Vector2隐式转换正常工作,但自投说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));
}
另一件事可能是在某些模板元编程带来,使安全转换的转换构造函数。
在我看来,提升并不包含这样的type_trait
,因此我推出了自己的。
它有点简化:目标必须至少与源一样大,并且如果源为浮点,则目标不能为整数。但是,它忽略了签名问题以及浮点类型是否可以表示整型的整个范围(例如float不能精确存储所有32位整数,但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;
}
我不方法破解没想到有什么办法为你的演员创建你自己的编译器警告。
你想要的东西是不可能的,因为它依赖于编译器对涉及类型的特殊知识,而且你不能向编译器教授这些东西。
你表现应该做到以下的项目:
Float a = 5.5;
应该毫无怨言工作。
std::string s = a;
应该给予一定的编译器错误,不一定一样使用POD浮动,但它仍然会拒绝,因为你的浮动没有一个const char *运营商。 (如果是这样,删除它导致此错误。)
Int x = a;
你仍然应该得到一个关于可能的数据丢失警告这里,除非浮动具有“操作INT()”。如果是这样,删除它,所以编译器被迫使用“运算符float()”,导致警告。
Int y = (int)a;
应该没有抱怨地工作。
Int z = static_cast<int>a;
这应该和前面的效果一样。 (他们之间有技术上的区别,但在这种情况下,他们应该没有关系。)
Float b = c;
你不显示'c'是什么,所以我不能说这会做什么。
static_cast 通常是安全的,并且会给你你所期望的 - 无论如此,或者它将无法编译。 reinterpret_cast 是危险的:它会编译,它会运行,你会得到一些根本没有意义的东西。 – 2009-10-06 22:05:24
是的,你是对的。我将编辑帖子。 – 2009-10-06 22:13:59
我加了c是:) – 2009-10-07 09:10:16