Good way of converting user-defined pointers
-
Let us imagine that I have a class which has pointer semantics:
template<class T> class MyPointer { //This class differs from simple pointer by having someAdditionalData private: T *pointer; int someAdditionalData; public: inline MyPointer(void): pointer(NULL), someAdditionalData(0) {;} //Default constructor inline MyPointer(MyPointer<T> const &p): pointer(p.pointer), someAdditionalData(p.someAdditionalData) {;} //Copy constructor inline MyPointer(T *const p): pointer(p), someAdditionalData(0) {;} //Custom constructor inline MyPointer<T> *operator->(void) const {return pointer;} //Arrow operator inline MyPointer<T> &operator*(void) const {return *pointer;} //Dereference operator inline int &SomeAdditionalData(void) {return someAdditionalData;} //Really important method };I also have another class which this pointer points to:
struct ClassToPointTo { int firstMember; int secondMember; }; MyPointer<ClassToPointTo> GeneratePointer(void) { //Some code here which calculates pointer and its someAdditionalData } ... MyPointer<ClassToPointTo const> const p( GeneratePointer() ); //I really like to write "const" where I canThe first problem is that
MyPointer<ClassToPointTo>is not automatically converted intoMyPointer<ClassToPointTo const>(I know why, but I don't know how to fix it), and the second, the main problem is following:I need to convert pointer
pfrom "ClassToPointTo const" type into one that will point to thefirstMemberof*pobject *without losingsomeAdditionalData*. I have functionGeneratePointer()which will make pointer havingsomeAdditionalData, but I need to work only with pointers tofirstMembers of the objects:MyPointer<int const> const p( WhatINeedToWriteHere??? GeneratePointer() ??? );I need fast and good-looking way of doing such conversion.
-
SAn schrieb:
The first problem is that
MyPointer<ClassToPointTo>is not automatically converted intoMyPointer<ClassToPointTo const>(I know why, but I don't know how to fix it)Maybe like this?
template <typename T> class MyPointer; template <typename T> struct MyPointerConversion { operator MyPointer<const T>() const { // ... } }; template <typename T> struct MyPointerConversion<const T> { }; template <typename T> class MyPointer : public MyPointerConversion<T> { // ... };A conversion constructor doesn't work because you would have to write
MyPointer(const MyPointer<typename remove_const<T>::type>& origin);which might have the same signature as the copy constructor (
remove_constis a metafunction that removes theconstqualifier from a type).Concerning your second problem: Can't it be solved by using a conversion operator (or better a function, to avoid implicit conversions), too?
-
Nexus schrieb:
A conversion constructor doesn't work because you would have to write
MyPointer(const MyPointer<typename remove_const<T>::type>& origin);which might have the same signature as the copy constructor (
remove_constis a metafunction that removes theconstqualifier from a type).sfinae helps
template <typename U> MyPointer(const MyPointer<U>& origin, typename enable_if< is_same< T, const U > >::type* = 0);A template constructor is never a copy constructor.
with meta functions is_same and enable_if, which can be found in tr1 or boost.derivation could be used as well, T->const T would then involve intentional slicing
template<class T> class MyPointer : public MyPointer< const T > { ... // hide any functions from base or overload with using, depending on whether constness is supposed to be transitive or not }; template <class T> class MyPointer< const T > { ... };template<class T> class MyPointer { ... // eat any MyPointer and a corresponding pointer to member template <typename U, typename V> MyPointer(const MyPointer<U>& other, V U::* pm ) : pointer( &( *other ).*pm ), someAdditionalData( other.SomeAdditionalData() ) {} ... }; MyPointer<ClassToPointTo const> const p( GeneratePointer(), &ClassToPointTo::firstMember );
-
camper schrieb:
template<class T> class MyPointer { ... // eat any MyPointer and a corresponding pointer to member template <typename U, typename V> MyPointer(const MyPointer<U>& other, V U::* pm ) : pointer( &( *other ).*pm ), someAdditionalData( other.SomeAdditionalData() ) {} ... }; MyPointer<ClassToPointTo const> const p( GeneratePointer(), &ClassToPointTo::firstMember );Last 2 weeks I trying to understand this but without any success.
&ClassToPointTo::firstMember
Such pointers are beyond my understanding.
-
I think this should be an ordinary memberfunction pointer:
http://www.newty.de/fpt/callback.html#member
-
drakon schrieb:
I think this should be an ordinary memberfunction pointer:
http://www.newty.de/fpt/callback.html#memberIt could be a pointer to member function if V is a function type, but that would be pointless with regards to the purpose of that class. I was thinking of a pointer to an ordinary non-function member.
-
SAn schrieb:
I need to convert pointer
pfrom "ClassToPointTo const" type into one that will point to thefirstMemberof*pobject *without losingsomeAdditionalData*. I have functionGeneratePointer()which will make pointer havingsomeAdditionalData, but I need to work only with pointers tofirstMembers of the objects:MyPointer<int const> const p( WhatINeedToWriteHere??? GeneratePointer() ??? );I need fast and good-looking way of doing such conversion.
I'm afraid that particular pig won't fly. At least not without a global map, which again is problematic and/or slow in multi-threaded environments.
If there were a "good" way (whether eays or not), I'm sure one of the smarter among the C++ community would already have found it, and integrated it into the boost::shared_ptr implementation. (As a way to get a shared_ptr from a raw-pointer, that shares ownership with other existing shared_ptrs.)
-
template<typename T> class pointer { T* ptr; public: explicit pointer(T* p=0) : ptr(p) {} T* get() const {return ptr;} T* operator->() const {return ptr;} T& operator*() const {return *ptr;} template<typename U> pointer(pointer<U> const& x, typename boost::enable_if< boost::is_convertible<U*,T*> >::type* =0) : ptr(x.get()) {} };(ungetestet)