我正在尝试替换类型,typedef
从内置整型类型中获得,在具有自定义类的大型项目中使用,这将实现一些附加功能,例如避免赋值时截断等。但是该项目广泛使用像 reinterpret_cast<void*>(value)
这样的转换。 。我做了一个天真的尝试来实现 operator void*()
在我的新类(class)中,但显然这并不能reinterpret_cast
,只允许static_cast
至void*
。代码如下:
#include <cstdlib>
#include <type_traits>
#define USE_NEW_VALUE_TYPE
#ifdef USE_NEW_VALUE_TYPE
struct Value
{
size_t value;
operator void* () { return reinterpret_cast<void*>(value); }
};
static_assert(std::is_pod<Value>::value,"Value is not POD");
#else
typedef size_t Value;
#endif
int main()
{
Value v{5};
void* p=reinterpret_cast<void*>(v); // This is how the project uses it
}
我认为如果该类是 POD,这将允许我做类似 reinterpret_cast
这样的事情。但这段代码给了我一个编译错误:
invalid cast from type ‘Value’ to type ‘void*’
所以我的问题是:如何添加对这样的 reinterpret_cast
的支持,这样我就不必手动将其切换到 static_cast
在项目的每个部分?
最佳答案
不幸的是,reinterpret_cast
并不是为此而设计的。这适用于 POD 类型的原因是 cppreference website 上的#3。 :
A value of any integral or enumeration type can be converted to a pointer type. A pointer converted to an integer of sufficient size and back to the same pointer type is guaranteed to have its original value, otherwise the resulting pointer cannot be dereferenced safely (the round-trip conversion in the opposite direction is not guaranteed; the same pointer may have multiple integer representations) The null pointer constant NULL or integer zero is not guaranteed to yield the null pointer value of the target type; static_cast or implicit conversion should be used for this purpose.
而且,我相信 §12.3.2 在这里发挥着作用:
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
简而言之:用户定义的转换不参与reinterpret_casts
的解析。
可能的解决方案
1.显式取v的地址:
void* p=reinterpret_cast<void*>(&v);
2.按照您的方式定义了operator void*()
,您可以编写
void *p = v;
注意:这可能会由于不需要的隐式转换而引发一系列问题
3.按照您自己所说使用static_cast
。
注意:使用 &v
而不是定义 operator void*()
,原因与第 2 条相同
4. 理想情况下,但可能不切实际,修复需要将类强制转换为 void 的底层设计问题
没有。 3 可能是这里最不痛苦的解决方案。
编辑评论
这里有两种方法:
1. 使用重载的取址运算符 (operator&
)。这可能无法实现,具体取决于 Value
的使用方式。
#include <cstdlib>
struct Value
{
size_t value;
void* operator &() { return reinterpret_cast<void*>(value); }
};
int main()
{
Value v;
void* p=reinterpret_cast<void*>(&v); // This is how the project uses it
}
2.实现一个运算符uintptr_t
。虽然这需要详细的双重转换,但它将转换转移到 Value
类中,并且 uintptr_t
是 guaranteed能够容纳 void*
。
#include <cstdlib>
struct Value
{
size_t value;
operator uintptr_t() { return static_cast<uintptr_t>(value); }
};
int main()
{
Value v;
void* p=reinterpret_cast<void*>(static_cast<uintptr_t>(v)); // This is how the project uses it
// or less verbose
void* p2=reinterpret_cast<void*>(uintptr_t(v));
}
关于c++ - POD 类型如何添加对reinterpret_cast 的支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31673850/