![](/img/trans.png)
[英]Why does Visual C++ warn on implicit cast from const void ** to void * in C, but not in C++?
[英]c++ - how to properly overload operator to do implicit type cast from __generic_buffer<void*> to __generic_buffer<const void*>?
简单来说,我有以下代码:
template<typename p>
requires(std::is_pointer<p>::value)
struct __generic_buffer
{
p baseptr;
size_t size;
// member functions go here
};
using buffer = __generic_buffer<void*>;
using const_buffer = __generic_buffer<const void*>;
我希望能够写出这样的东西:
uint8_t arr[64];
buffer b {arr, 64};
const_buffer cb = b;
所以基本上我希望指向可修改内存区域的buffer
可以自由转换为指向常量内存区域的const_buffer
,但不是相反,只是通常的指针行为。 此外,我更喜欢这种转换与__generic_buffer
任何其他实例化__generic_buffer
,例如__generic_buffer<int*>
到__generic_buffer<const int*>
。
先说第一件事。 带有__
类型由 C++ 标准为您的编译器和标准库保留。 在程序中使用它们会使您的程序格式错误,无需诊断。 (另外, _T
以_
开头,然后是大写字母)。
这种坏习惯来自于复制std
headers之类的编码风格。 他们被允许这样做,实际上必须这样做,因为如果他们调用了bob
,那么有人可以合法地#define bob alice
并破坏头文件。
有两种方法可以做你想做的事。
其中之一涉及编写转换构造函数,另一个涉及转换运算符。
我将展示操作员的方式。
template<class P>
requires(std::is_pointer<P>::value)
struct generic_buffer
{
P baseptr;
size_t size;
template<class U>
requires(std::is_same<std::remove_cv_t<std::remove_pointer_t<U>>, std::remove_pointer_t<P>>::value)
operator generic_buffer<U>() const {
return {baseptr, size};
}
// member functions go here
};
我可能会写一个 trait 而不是这样做requires
内联,但基本上我们在从*U
删除const
和volatile
后检查*U
是否与*P
类型相同。
如果是这样,我们允许这个转换运算符存在。
在里面,我们使用隐式转换来转换指针类型。
现在,这并不完美,因为我们真的想检查删除 const、volatile 或两者中的任何一个是否会使其匹配。 您可能想要编写一个执行该测试的类型函数。
构造器的方式就是上面的,但是倒退了。 声明构造函数对自动构造函数和类型的琐碎性有一些影响,而像这样的运算符则没有,因此为了避免离题,我将其实现为运算符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.