ARTICLE AD BOX
I'm trying to create a pointer like type wrapper for CUDA device pointers, but ran into a problem trying to define T& operator[]. By default, the compiler complains that I'm attempting to "form reference from void" So I attempted to use C++20 concepts in order to avoid this. I get the same error (examples all normal C++ code, not cuda, and have the same issues):
#include <type_traits> #include <concepts> template<typename T> struct TestPointerLike{ T* m_data; [[nodiscard]] T& operator[](std::integral auto i) const noexcept requires (!std::same_as<std::remove_cvref_t<T>, void>) { return m_data[i]; } }; int main() { TestPointerLike<void> test; } <source>: In instantiation of 'struct TestPointerLike<void>': <source>:14:27: required from here 14 | TestPointerLike<void> test; | ^~~~ <source>:8:9: error: forming reference to void 8 | T& operator[](std::integral auto i) const noexcept requires (!std::same_as<std::remove_cvref_t<T>, void>) { | ^~~~~~~~ Compiler returned: 1See godbolt:
https://godbolt.org/z/aarrovhhv
I tried to figure out how to solve this, and I saw this question: requires clause for a non-template member function in a template class
And thought it was complaining about the solution I thought would work but didn't not working. The answer doesn't work. I get the same issue.
#include <type_traits> #include <concepts> template<typename T> struct TestPointerLike{ T* m_data; [[nodiscard]] T& operator[](std::integral auto i) const noexcept requires (!std::same_as<std::remove_cvref_t<T>, void>); }; template <class T> T& TestPointerLike<T>::operator[](std::integral auto i) const noexcept requires (!std::same_as<std::remove_cvref_t<T>, void>){ return m_data[i]; } int main() { TestPointerLike<void> test; } <source>: In instantiation of 'struct TestPointerLike<void>': <source>:18:27: required from here 18 | TestPointerLike<void> test; | ^~~~ <source>:8:9: error: forming reference to void 8 | T& operator[](std::integral auto i) const noexcept requires (!std::same_as<std::remove_cvref_t<T>, void>); | ^~~~~~~~ Compiler returned: 1See godbolt link: https://godbolt.org/z/jWGeffqEx
And the first actual solution (I realized they posted as a solution, not a problem) didn't work (first godbolt link tests that).
The only thing I've found to actually work is this:
#include <type_traits> #include <concepts> template<typename T> struct TestPointerLike{ T* m_data; template<typename U = T> requires(!std::same_as<std::remove_cvref_t<T>, void> && std::same_as<T, U>) [[nodiscard]] U& operator[](std::integral auto i) const noexcept{ return m_data[i]; } }; int main() { TestPointerLike<void> test; }see godbolt link https://godbolt.org/z/5YMTYYd43
Is there away to get this to work more or less like I intended it to in the first example?
