简体   繁体   English

c ++ - 如何正确重载运算符以从 __generic_buffer 进行隐式类型转换<void*>到 __generic_buffer<const void*> ?

[英]c++ - how to properly overload operator to do implicit type cast from __generic_buffer<void*> to __generic_buffer<const void*>?

To put it simple, i have the following code:简单来说,我有以下代码:

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*>;

and i want to be able to write something like that:我希望能够写出这样的东西:

uint8_t arr[64];
buffer b {arr, 64};
const_buffer cb = b;

so basically i want buffer pointing to modifiable memory area to be freely castable to const_buffer pointing to constant memory area, but not the other way around, just how usual pointers behave.所以基本上我希望指向可修改内存区域的buffer可以自由转换为指向常量内存区域的const_buffer ,但不是相反,只是通常的指针行为。 Also, i'd prefer this conversion to work with any other instantiation of __generic_buffer , eg __generic_buffer<int*> to __generic_buffer<const int*> .此外,我更喜欢这种转换与__generic_buffer任何其他实例化__generic_buffer ,例如__generic_buffer<int*>__generic_buffer<const int*>

First things first.先说第一件事。 Types with __ in them are reserved by the C++ standard for your compiler and the standard library.带有__类型由 C++ 标准为您的编译器和标准库保留。 Use of them in programs makes your program ill-formed, no diagnostic required.在程序中使用它们会使您的程序格式错误,无需诊断。 (also, _T starting with an _ and then a capital letter). (另外, _T_开头,然后是大写字母)。

This kind of bad habit comes from copying the coding style of std headers and the like.这种坏习惯来自于复制std headers之类的编码风格。 They are allowed to do that, and in fact must do that, because if they called something bob , someone could legally #define bob alice and break the header file.他们被允许这样做,实际上必须这样做,因为如果他们调用了bob ,那么有人可以合法地#define bob alice并破坏头文件。


There are two ways to do what you want.有两种方法可以做你想做的事。

One of them involves writing a converting constructor, the other a converting operator.其中之一涉及编写转换构造函数,另一个涉及转换运算符。

I'll show the operator way.我将展示操作员的方式。

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

I might write a trait rather than do that requires inline, but basically we check if *U is the same type as *P after removing const and volatile from *U .我可能会写一个 trait 而不是这样做requires内联,但基本上我们在从*U删除constvolatile后检查*U是否与*P类型相同。

If so, we allow this conversion operator to exist.如果是这样,我们允许这个转换运算符存在。

Inside, we use implicit conversion to convert the pointer types.在里面,我们使用隐式转换来转换指针类型。

Now, this isn't perfect , because we really want to check if removing either of const, volatile or both would make it match.现在,这并不完美,因为我们真的想检查删除 const、volatile 或两者中的任何一个是否会使其匹配。 You might want to write a type function that does that test.您可能想要编写一个执行该测试的类型函数。

The constructor way is just the above, but backwards.构造器的方式就是上面的,但是倒退了。 Declaring a constructor has some impact on the automatic constructors and the triviality of a type, while an operator like this doesn't, so to avoid having to digress into those issues I implemented it as an operator.声明构造函数对自动构造函数和类型的琐碎性有一些影响,而像这样的运算符则没有,因此为了避免离题,我将其实现为运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM