|
| 1 | +# Casting multi_ptr pointers |
| 2 | + |
| 3 | +## Motivation |
| 4 | + |
| 5 | +The current SYCL 1.2.1 specification contains the `multi_ptr` class |
| 6 | +which is designed mostly for OpenCL interoperability |
| 7 | +and calling certain functions which rely on OpenCL builtins. |
| 8 | +The `multi_ptr` class has two template parameters: |
| 9 | +`ElementType` as the type of the underlying data, |
| 10 | +and `Space` to designate the address space of the pointer. |
| 11 | +It is not allowed to cast pointers to a different address space, |
| 12 | +but casting pointers to a different underlying type is completely valid C++, |
| 13 | +within the type restrictions for the cast. |
| 14 | + |
| 15 | +Programmers wanting to cast `multi_ptr<A, Space>` to `multi_ptr<B, Space>` |
| 16 | +don't have many options to do so in SYCL 1.2.1. |
| 17 | +There are only two specified casts in SYCL 1.2.1: |
| 18 | + * Using `static_cast` to cast `multi_ptr<A, Space>` to `multi_ptr<void, Space>` |
| 19 | + (defined through an explicit conversion operator) |
| 20 | + * Using `static_cast` to cast `multi_ptr<void, Space>` to `multi_ptr<B, Space>` |
| 21 | + (defined through an explicit conversion operator) |
| 22 | + |
| 23 | +Therefore, the only option to perform a cast from |
| 24 | +`multi_ptr<A, Space>` to `multi_ptr<B, Space>` |
| 25 | +is to use both casts like so: |
| 26 | +```cpp |
| 27 | +// Using global_ptr here to simplify the code |
| 28 | +// decltype(multiPtrA) == global_ptr<A> |
| 29 | +auto multiPtrB = static_cast<global_ptr<B>>(static_cast<global_ptr<void>>(multiPtrA)); |
| 30 | +``` |
| 31 | + |
| 32 | +This is problematic on a few levels: |
| 33 | + * Verbosity |
| 34 | + * Only allows static casts |
| 35 | + * Allows casting the underlying `A*` pointer to a `B*` pointer |
| 36 | + even if the type system forbids it |
| 37 | + * Does not handle `const` cases |
| 38 | + |
| 39 | +Therefore, there is a clear need to provide more casting options for the `multi_ptr` class |
| 40 | +in order to make the casting safer and easier to use. |
| 41 | + |
| 42 | +## Summary |
| 43 | + |
| 44 | +This proposal adds a few explicit conversion operators |
| 45 | +as member functions of the `multi_ptr` class |
| 46 | +and also adds several free functions to the `cl::sycl` namespace |
| 47 | +that follow the naming and semantics of the `std::shared_ptr` pointer cast functions |
| 48 | +defined by the C++17 standard: https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast. |
| 49 | + |
| 50 | +## Explicit conversion operators |
| 51 | + |
| 52 | +The new interface of the `multi_ptr` class would look like this: |
| 53 | + |
| 54 | +```cpp |
| 55 | +namespace cl { |
| 56 | +namespace sycl { |
| 57 | + |
| 58 | +template <typename ElementType, access::address_space Space> |
| 59 | +class multi_ptr { |
| 60 | + public: |
| 61 | + /// All existing members here |
| 62 | + |
| 63 | + ... |
| 64 | + |
| 65 | + // Explicit conversion to `multi_ptr<U, Space>` |
| 66 | + template <typename U> |
| 67 | + explicit operator multi_ptr<U, Space>() const; |
| 68 | + |
| 69 | + // Explicit conversion to `multi_ptr<const ElementType, Space>` |
| 70 | + explicit operator multi_ptr<const ElementType, Space>() const; |
| 71 | +}; |
| 72 | + |
| 73 | +template <access::address_space Space> |
| 74 | +class multi_ptr<void, Space> { |
| 75 | + public: |
| 76 | + /// All existing members here |
| 77 | + |
| 78 | + ... |
| 79 | + |
| 80 | + // Explicit conversion to `multi_ptr<const void, Space>` |
| 81 | + explicit operator multi_ptr<const void, Space>() const; |
| 82 | +}; |
| 83 | + |
| 84 | +} // namespace sycl |
| 85 | +} // namespace cl |
| 86 | +``` |
| 87 | +
|
| 88 | +The conversion operator to `multi_ptr<U, Space>` replaces |
| 89 | +the existing explicit conversion to `multi_ptr<void, Space>`. |
| 90 | +
|
| 91 | +TODO(Peter): Table |
| 92 | +
|
| 93 | +TODO(Peter): Handle multi_ptr<const void, Space> |
| 94 | +
|
| 95 | +## Conversion functions |
| 96 | +
|
| 97 | +TODO(Peter) |
0 commit comments