最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - invalid user-defined conversion from Pointer<Node> to Node* - Stack Overflow

programmeradmin2浏览0评论
#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
  • 1 (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:22
  • 1 Pointer<T>& operator=(Pointer<T> other) { if (this != &other) is wrong if you pass by value. – Jarod42 Commented Mar 25 at 9:27
  • I think your approach is flawed. You ought to storing a non-owning raw pointer, not offset and (as Jarod42 mentioned) the UB. The offset 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
  • I corrected the issue in the operator=. The purpose of offset here is to create these pointers in a shared memory, in which raw pointer will render useless if I try to read from a different process. So the offset between the Pointer object and actual T object is useful for reaching the right object in the shared memory which has been mapped to a different process. – Tejas Sharma Commented Mar 26 at 8:45
Add a comment  | 

2 Answers 2

Reset to default 4

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

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.

发布评论

评论列表(0)

  1. 暂无评论