![]() |
| | #1 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 16,078
| Assignment issues Continuing on the shared pointer, I cannot assign the right-hand side m_ptr to the left-hand side because it's a templated-type pointer (see code). So, I wrapped the pointer in a struct, yet I still cannot seem to get it right. I was hoping anyone with some good eyes or some free time could help me with it. Minimal code snippet: Code: #ifndef MAD_SHARED_PTR_175451_H
#define MAD_SHARED_PTR_175451_H
#ifndef NULL
#define NULL 0
#endif
const int nullptr = NULL;
#include <assert.h>
class nullptr_t {};
template<int Bits> class ptr_thread_dangerous
{
};
class Derived;
template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32> class mad_shared_ptr
{
protected:
template<typename T, int Bits> struct sptr
{
};
template<typename T, int Bits> class sptr_wrapper
{
public:
sptr_wrapper(sptr<T, Bits>* p): m_p(p) {}
/*template<typename OtherT> */sptr_wrapper& operator = (const sptr_wrapper<Derived, 32>& rhs)
{
m_p->p = rhs.p;
m_p->RefCount = rhs.RefCount;
m_p->pDeleter = rhs.pDeleter;
}
protected:
sptr<T, Bits>* m_p;
};
typedef sptr<T, Bits> ptr_t;
public:
mad_shared_ptr(): m_ptr(nullptr) { }
template<typename Other> mad_shared_ptr(Other* p): m_ptr(nullptr) { *this = p; }
template<typename Other> mad_shared_ptr(const mad_shared_ptr<Other>& rhs): m_ptr(nullptr) { *this = rhs; }
template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
{
m_ptr = rhs.m_ptr;
return *this;
}
protected:
sptr_wrapper<T, Bits> m_ptr;
template<typename Other, template<int> class thread_safety, int Bits> friend class mad_shared_ptr;
};
#endif // MAD_SHARED_PTR_175451_H
Code: #include <... mad_shared_ptr.h>
class Base {};
class Derived: public Base {};
int main()
{
mad_shared_ptr<Base> p;
mad_shared_ptr<Derived> p2 = new Derived();
p = p2;
}
1>error C2679: binary '=' : no operator found which takes a right-hand operand of type 'const mad_shared_ptr<T>::sptr_wrapper<T,Bits>' (or there is no acceptable conversion) 1> with 1> [ 1> T=Derived, 1> Bits=32 1> ] 1> could be 'mad_shared_ptr<T>::sptr_wrapper<T,Bits> &mad_shared_ptr<T>::sptr_wrapper<T,Bits>::opera tor =(const mad_shared_ptr<T>::sptr_wrapper<Derived,32> &)' 1> with 1> [ 1> T=Base, 1> Bits=32 1> ] 1> or 'mad_shared_ptr<T>::sptr_wrapper<T,Bits> &mad_shared_ptr<T>::sptr_wrapper<T,Bits>::opera tor =(const mad_shared_ptr<T>::sptr_wrapper<T,Bits> &)' 1> with 1> [ 1> T=Base, 1> Bits=32 1> ] 1> while trying to match the argument list '(mad_shared_ptr<T>::sptr_wrapper<T,Bits>, const mad_shared_ptr<T>::sptr_wrapper<T,Bits>)' 1> with 1> [ 1> T=Base, 1> Bits=32 1> ] 1> and 1> [ 1> T=Derived, 1> Bits=32 1> ] Basically it's saying it can't find an assignment operator that takes sptr_wrapper<Base, 32> (which the lhs should be, and is, according to the error) and a sptr_wrapper<Derived, 32> (the very exact operator I tried adding). If anyone spots a problem, I'd be grateful for any help.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2010 Ultimate, C++0x "Thanks Elysia. You're a programming master! How the hell do you know every thing?" "Thanks for all your help. It's obvious yall really know what you're talking about when it comes to OOP/C++ stuff." Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #2 | |
| The larch Join Date: May 2006
Posts: 3,333
| Firstly you have lots of problems shadowing template parameters. But then the problem still remains unless I just lift the nested classes out of the mad_shared_ptr class.
__________________ I might be wrong. Quote:
| |
| anon is offline | |
| | #3 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 16,078
| Ah, I wonder why it works if I move them outside?
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2010 Ultimate, C++0x "Thanks Elysia. You're a programming master! How the hell do you know every thing?" "Thanks for all your help. It's obvious yall really know what you're talking about when it comes to OOP/C++ stuff." Quoted... at least once. Quote:
| |
| Elysia is offline | |
| | #4 |
| Guest Join Date: Aug 2001
Posts: 5,249
| Also: 1) The code for 'sptr' in your example is incomplete 2) How exactly does class 'Derived' tie into 'mad_shared_ptr'? 3) 'mad_shared_ptr' has no assignment operator for a pointer to 'T'. 4) The purpose of 'sptr_wrapper' is unclear. Can you explain that? Further, where is it supposed to get a pointer to an 'sptr', anyway? 5) Template functions expecting another type of 'mad_shared_ptr' should forward *all* of the template parameters - not just the first one. 6) Your back to the same problem you had earlier, this time with 'sptr_wrapper' (only now in a more complicated context). Namely, a mad_shared_ptr<T, thread_safety, Bits>::sptr_wrapper<T2, Bits2> with different parameters will, of course, yield a completely different type, so the protected qualifier prevents access. 7) The idea of assigning, say, a mad_shared_ptr< float > to a mad_shared_ptr< string > doesn't even really make sense. How is that supposed to work? Lot's of confusing issues, IMO. Maybe you could describe more clearly what you're wanting to do? |
| Sebastiani is offline | |
| | #5 | ||||||||
| Mysterious C++ User Join Date: Oct 2007
Posts: 16,078
| Quote:
Quote:
Quote:
This structure contains the actual reference counting, which is shared among all similar pointers. Hence, in the assignment operator, I would need to duplicate the pointer address from the rhs to the lhs. But that's impossible since sptr<Base, 32> != sptr<Derived, 32>. What do we do then? We need a function that makes it possible to assign the rhs to lhs if and only if it's possible to assign rhs.m_ptr->p to lhs.m_ptr->p (the actual pointee it's encapsulating). This should work if rhs's pointer type is derived from lhs's pointer type. Creating a global assignment operator is not possible, so I made a wrapper so that I could overload operator = instead. Quote:
Quote:
Quote:
However, the idea is to use the compiler as a tool here. In the end, it should be assigning a string* to a float* and obviously that won't work. But if we assign a mad_shared_ptr<Derived> to a mad_shared_ptr<Base>, then in the end we should get an assignment of Derived* to Base*. This is the idea. Quote:
I need to assign a mad_shared_ptr<Derived> to a mad_shared_ptr<Base>. I would be happy to post the full code, that you may examine it. You should be aware that it does rely on boost. Although I could make efforts to reduce that dependancy.
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2010 Ultimate, C++0x "Thanks Elysia. You're a programming master! How the hell do you know every thing?" "Thanks for all your help. It's obvious yall really know what you're talking about when it comes to OOP/C++ stuff." Quoted... at least once. Quote:
| ||||||||
| Elysia is offline | |
| | #6 | |||||||
| Guest Join Date: Aug 2001
Posts: 5,249
| Quote:
Quote:
Quote:
Quote:
Code:
template < typename A, typename B = int, typename C = int >
struct foo
{ };
template < typename A >
void bar( foo< A > const& )
{ }
int main( void )
{
bar( foo< int, double, double >( ) );
}
Quote:
![]() Quote:
Quote:
| |||||||
| Sebastiani is offline | |
| | #7 | |
| Mysterious C++ User Join Date: Oct 2007
Posts: 16,078
| I took the liberty of trying another approach. I still get the pesky access errors, however. Don't know if it will yield more errors beyond what I get and if any linker errors. Anyway, I did promise the code so you could see what's going on, so here it is: Code: #ifndef MAD_SHARED_PTR_175451_H
#define MAD_SHARED_PTR_175451_H
#ifndef NULL
#define NULL 0
#endif
const int nullptr = NULL;
//#include <boost/cstdint.hpp>
#include <memory>
#include <assert.h>
namespace boost
{
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
}
class nullptr_t {};
template<typename T> T* mad_ptr_clone(const T* pOld) { return smad_ptr_int<T, boost::is_polymorphic<T>::value>::Clone(pOld); }
template<typename T, bool Polymorphic> struct smad_ptr_int
{
static T* Clone(const T* pOld) { return pOld->Clone(); } // IsPolymorphic = yes
};
template<typename T> struct smad_ptr_int<T, false>
{
static T* Clone(const T* pOld) { return new T(*pOld); } // IsPolymorphic = no
};
template<int N> struct ptr_bits { /*typedef current_amount_of_bits_not_supported rf_type;*/ };
template<> struct ptr_bits<32> { typedef boost::uint32_t rf_type; };
template<> struct ptr_bits<64> { typedef boost::uint64_t rf_type; };
#if _WIN32_WINNT >= 0x600 && WINVER >= 0x600
#include <windows.h>
template<int Bits> class ptr_thread_safe { };
template<> class ptr_thread_safe<32>
{
public:
static void Increment(void* p) { InterlockedIncrement((LONG*)p); }
static void Decrement(void* p) { InterlockedDecrement((LONG*)p); }
};
template<> class ptr_thread_safe<64>
{
public:
static void Increment(void* p) { InterlockedIncrement64((LONGLONG*)p); }
static void Decrement(void* p) { InterlockedDecrement64((LONGLONG*)p); }
};
#endif
template<int Bits> class ptr_thread_dangerous
{
public:
template<typename T> static void Increment(T* p) { (*p)++; }
template<typename T> static void Decrement(T* p) { (*p)--; }
};
class Derived;
template<typename T, int Bits> struct sptr;
template<typename T, int Bits, typename OtherT> sptr<T, Bits>* CastToSptrT(sptr<OtherT, Bits>* p)
{
T* pTest = p->p; // Test if Other is implicitly convertable to T.
return (sptr<T, Bits>*)p;
}
template<typename T, int Bits> struct sptr
{
template<typename T> class deleter_base { public: virtual void destroy(T* p) = 0; };
template<typename T, typename deleter_t> class deleter: public deleter_base<T>
{
public:
deleter(deleter_t delete_fnc): m_delete_fnc(delete_fnc) { }
virtual void destroy(T* p) { m_delete_fnc(p); }
private:
deleter_t m_delete_fnc;
};
sptr(): p(nullptr), RefCount(0), pDeleter(nullptr) { }
T* p;
typename ptr_bits<Bits>::rf_type RefCount;
deleter_base<T>* pDeleter;
template<typename T, int Bits, typename OtherT> friend sptr<T, Bits>* CastToSptrT <> (sptr<OtherT, Bits>* p);
};
//template<typename T, int Bits> class sptr_wrapper
//{
//public:
// sptr_wrapper(sptr<T, Bits>* p): m_p(p) {}
// template<typename OtherT> sptr_wrapper& operator = (const sptr_wrapper<OtherT, Bits>& rhs)
// {
// assert(m_p);
// assert(rhs.m_p);
// m_p->p = rhs.m_p->p;
// m_p->RefCount = rhs.m_p->RefCount;
// m_p->pDeleter = rhs.m_p->pDeleter;
// }
//
// sptr<T, Bits>* operator -> () { assert(m_p); return m_p; }
//
// sptr<T, Bits>* get() { assert(m_p); return m_p; }
// void set(sptr<T, Bits>* p) { assert(p); m_p = p; }
//
//protected:
// sptr<T, Bits>* m_p;
// template<typename T, int Bits> friend class sptr_wrapper;
//};
template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32> class mad_shared_ptr
{
protected:
typedef void (mad_shared_ptr::* bool_type)() const;
typedef sptr<T, Bits> ptr_t;
public:
mad_shared_ptr(): m_ptr(nullptr) { }
template<typename Other> mad_shared_ptr(Other* p): m_ptr(nullptr) { *this = p; }
template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc): m_ptr(nullptr)
{
std::auto_ptr< ptr_t::deleter_base<T> > pDeleter( new ptr_t::deleter<T, Deleter>(delete_fnc) );
*this = p;
m_ptr->pDeleter = pDeleter.release();
}
mad_shared_ptr(const mad_shared_ptr& rhs): m_ptr(nullptr) { *this = rhs; }
template<typename Other> mad_shared_ptr(const mad_shared_ptr<Other>& rhs): m_ptr(nullptr) { *this = rhs; }
mad_shared_ptr(const nullptr_t&): m_ptr(nullptr) { }
~mad_shared_ptr() { DecRefCount(m_ptr); }
bool unique() const { return (m_ptr->RefCount == 1); }
void make_unique()
{
if (unique())
return;
std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
pNewPtr->p = mad_ptr_clone(m_ptr->p);
pNewPtr->RefCount = 1;
pNewPtr->pDeleter = m_ptr->pDeleter;
DecRefCount(m_ptr);
m_ptr = pNewPtr.release();
}
void release()
{
DecRefCount();
m_p = nullptr;
m_RefCount = nullptr;
m_deleter = nullptr;
}
template<typename Other> mad_shared_ptr& operator = (Other* rhs)
{
if (m_ptr && rhs == m_ptr->p)
return *this;
ptr_t* pOldPtr = m_ptr;
std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
pNewPtr->p = rhs;
pNewPtr->RefCount++;
m_ptr = pNewPtr.release();
DecRefCount(pOldPtr);
return *this;
}
mad_shared_ptr& operator = (const mad_shared_ptr& rhs)
{
return operator = <T>(rhs);
}
template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
{
if (rhs == *this)
return *this;
//T* pTest = rhs.m_ptr->p; // Test if Other is implicitly convertable to T.
DecRefCount(m_ptr);
m_ptr = CastToSptrT<T>(rhs.m_ptr);
IncRefCount(m_ptr);
return *this;
}
mad_shared_ptr& operator = (const nullptr_t&)
{
DecRefCount(m_ptr);
m_ptr = nullptr;
return *this;
}
T& operator * () const { assert(m_ptr); return *m_ptr->p; }
T* operator -> () const { assert(m_ptr); return m_ptr->p; }
template<typename rhs_t>
friend bool operator == (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return (lhs.m_ptr == CastToSptrT<T>(rhs.m_ptr));
}
template<typename rhs_t>
friend bool operator != (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return !(lhs == CastToSptrT(rhs));
}
operator bool_type() const
{
return m_ptr && m_ptr->p ? &mad_shared_ptr::this_type_does_not_support_comparisons : nullptr;
}
protected:
void IncRefCount(sptr<T, Bits>* ptr)
{
thread_safety<Bits>::Increment(&ptr->RefCount);
}
void DecRefCount(sptr<T, Bits>*& ptr)
{
if (ptr == nullptr)
return;
thread_safety<Bits>::Decrement(&ptr->RefCount);
if (ptr->RefCount == 0)
{
if (ptr->pDeleter)
ptr->pDeleter->destroy(ptr->p);
else
delete ptr->p;
delete ptr;
ptr = nullptr;
}
}
void this_type_does_not_support_comparisons() const {}
sptr<T, Bits>* m_ptr;
template<typename OtherT, template<int> class thread_safety, int Bits> friend class mad_shared_ptr;
};
#endif // MAD_SHARED_PTR_175451_H
__________________ Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2010 Ultimate, C++0x "Thanks Elysia. You're a programming master! How the hell do you know every thing?" "Thanks for all your help. It's obvious yall really know what you're talking about when it comes to OOP/C++ stuff." Quoted... at least once. Quote:
Last edited by Elysia; 01-13-2010 at 12:59 PM. | |
| Elysia is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Menu | Krush | C Programming | 17 | 09-01-2009 02:34 AM |
| Assignment Operator, Memory and Scope | SevenThunders | C++ Programming | 47 | 03-31-2008 06:22 AM |
| Screwy Linker Error - VC2005 | Tonto | C++ Programming | 5 | 06-19-2007 02:39 PM |
| Help with a pretty big C++ assignment | wakestudent988 | C++ Programming | 1 | 10-30-2006 09:46 PM |
| A mini-compilier I made stuck in an infinite loop (lots of code) | dan06 | C++ Programming | 1 | 10-27-2006 01:21 PM |