?,c++,types,casting,type-conversion"/>

首页 > 解决方案 > c++ - 如何正确重载运算符以从 __generic_buffer 执行隐式类型转换到 __generic_buffer?

问题描述

简单地说,我有以下代码:

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<int*>__generic_buffer<const int*>

标签: c++typescastingtype-conversion

解决方案


第一件事。__C++ 标准为您的编译器和标准库保留其中包含的类型。在程序中使用它们会使您的程序格式错误,不需要诊断。(同样,_T以一个开头_,然后是一个大写字母)。

这种坏习惯来自于抄袭std标头之类的编码风格。他们被允许这样做,而且实际上必须这样做,因为如果他们调用了某些东西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
};

我可能会写一个特征而不是requires内联,但基本上我们检查是否与删除and from之后*U的类型相同。*Pconstvolatile*U

如果是这样,我们允许这个转换运算符存在。

在内部,我们使用隐式转换来转换指针类型。

现在,这并不完美,因为我们真的想检查删除 const、volatile 或两者中的任何一个是否会使其匹配。您可能想要编写一个执行该测试的类型函数。

构造方法就是上面的,但是倒过来了。声明构造函数对自动构造函数和类型的琐碎性有一些影响,而像这样的运算符则没有,因此为了避免不得不脱离这些问题,我将其实现为运算符。


推荐阅读