#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.
#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.
Share Improve this question edited Mar 25 at 9:18 Jarod42 219k15 gold badges196 silver badges330 bronze badges asked Mar 25 at 7:06 Tejas SharmaTejas Sharma 1021 silver badge12 bronze badges 4 |2 Answers
Reset to default 4The 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;
}
Your conversion operator's const
is misplaced. It should be
operator T*() const {
Your current code is equivalent to an IntWrapper
defining
operator int const();
which means that non-const IntWrapper
instances can be converted to ints, with the return value marked as const. But what you really want is for const instances to be converted to ints, and the return value marked as const doesn't matter because it's a copy anyway.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744213542a4563447.html
(char*)ptr - (char*)this;
is pedantically UB. not sure the purpose of offset.std::experimental::observer_ptr
might interest you. – Jarod42 Commented Mar 25 at 9:22Pointer<T>& operator=(Pointer<T> other) { if (this != &other)
is wrong if you pass by value. – Jarod42 Commented Mar 25 at 9:27offset
and (as Jarod42 mentioned) the UB. Theoffset
implementation (besides the UB) has a lot of problems. (The UB may seem to "work" on linear memory computers (but still UB), but won't work on segmented architectures or bank switched architectures.) – Eljay Commented Mar 25 at 11:23