1

我怎样才能铸造为用户定义类型相同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

回答

1

我不认为有办法。我能达到的最好的结果是,你想要生成警告的行根本不会编译。

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; 
} 
0

我不方法破解没想到有什么办法为你的演员创建​​你自己的编译器警告。

1

你想要的东西是不可能的,因为它依赖于编译器对涉及类型的特殊知识,而且你不能向编译器教授这些东西。

你表现应该做到以下的项目:

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'是什么,所以我不能说这会做什么。

+2

static_cast <>通常是安全的,并且会给你你所期望的 - 无论如此,或者它将无法编译。 reinterpret_cast <>是危险的:它会编译,它会运行,你会得到一些根本没有意义的东西。 – 2009-10-06 22:05:24

+0

是的,你是对的。我将编辑帖子。 – 2009-10-06 22:13:59

+0

我加了c是:) – 2009-10-07 09:10:16