#include <cstddef>
#include <stdexcept>
#include <cassert>
template <typename T>
class Pointer {
private:
std::ptrdiff_t offset;
std::ptrdiff_t calculateOffset(const T* ptr) const {
if (ptr == nullptr) return 0;
return (char*)ptr - (char*)this;
}
public:
Pointer() : offset(0) {}
Pointer(T* p) : offset(calculateOffset(p)) {}
Pointer(const Pointer<T>& other) :
offset(calculateOffset(other)) {}
Pointer(Pointer<T>&& other) noexcept : offset(other.offset) {
other.offset = 0;
}
~Pointer() {
offset = 0;
}
operator T* const() {
assert(offset != 0);
T* temp = (T*) ((char*)this + offset);
return temp;
}
Pointer<T>& operator=(Pointer<T> other) {
if (this != &other) {
T* temp = other;
offset = calculateOffset(temp);
}
return *this;
}
T* operator->() const {
T* ptr = *this;
assert(ptr != nullptr);
return ptr;
}
};
I am trying to create a seamless Pointer wrapper which can be used to replace raw pointers in my project. The problem I am facing is that I can't declare explicit getter function to get the pointer value because it will lead to lot of changes in the codebase. I tried creating this class with type conversion operator so that Pointer<T>
can be converted to T*
seamlessly.
I am now facing the error:
Pointer1.h:24:31: error: invalid user-defined conversion from 'const Pointer<Node>' to 'const Node*' [-fpermissive]
24 | offset(calculateOffset(other)) {}
| ~~~~~~~~~~~~~~~^~~~~~~
I scrapped through other questions and saw the discussion related to most vexing parse but I couldn't gather what I am doing wrong.
The operator T* const()
is a member function without const-qualifiers, whose return type is T* const
. So the this
pointer of this member function has type Pointer<T>*
. However, in the copy constructor Pointer(const Pointer<T>& other)
, other
is a const-qualified reference to Pointer<T>
.
You cannot call a non-const member function through a const-qualified reference, since you cannot use it initialize the this
pointer using the const-qualified reference other
without const_cast
.
So you should add a const qualifier to the function:
operator T* () const {
assert(offset != 0);
T* temp = (T*) ((char*)this + offset);
return temp;
}