Skip to main content
GameDev.net gamedev.net
🔒 Locked

Loki's SmartPtr

Started by Murrgon Nov 18, 2004 at 10:41 AM 10 replies 1.6k views
Original Post
Murrgon
Murrgon
Has anyone here used the SmartPtr class from Loki? I started experimenting with it and I have found a serious problem with it. Consider this: #include template class TSmartPtr : public Loki::SmartPtr < TYPE, Loki::RefCounted, // Our pointers will have reference counting Loki::AllowConversion, // Implicit conversion to contained pointer okay Loki::AssertCheck, // Assert checks requires Loki::DefaultSPStorage // Normal pointer-style storage > { }; int main() { TSmartPtr pInteger; pInteger = new int; return 0; } The above code will not compile. It gives an error that there is no binary operator that takes a right-hand 'int*' for the line 'pInteger = new int'. Is it just me, or does that seem really dumb. How are you supposed to initialize a smart pointer if you can't assign it a raw pointer? And don't tell me to use the constructor because it has the exact same problem. How the heck are you supposed to initialize this thing? Thanks
The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That''s funny ..."
Qw3r7yU10p!
Qw3r7yU10p!
int main(){  TSmartPtr<int> pInteger = TSmartPtr<int>(new int);  return 0;}


If you use a typedef it will make things easier.
typedef TSmartPtr<int> IntPtr;int main(){  IntPtr pInteger = IntPtr(new int);  return 0;}
Murrgon
Murrgon
I tried this:

  TSmartPtr<int> pInteger;  pInteger = TSmartPtr<int>(new int);


and now I get an "error C2440: 'type cast' : cannot convert from 'int *' to 'TSmartPtr'" (I'm using VC7.1). I am assuming this is because TSmartPtr doesn't have a constructor that can convert 'new int' to something it can use.
The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That''s funny ..."
Qw3r7yU10p!
Qw3r7yU10p!
Sorry I wasn't looking that you were inheriting.

I assume you're doing that so that you don't have to keep typing out all the policies for each new smart pointer you define.

If you just use a typedef instead of inheriting then it'll be fine.
Murrgon
Murrgon
How do you typedef a partial template specialization? I don't know how to form the syntax for such a beast.
The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That''s funny ..."
Sharlin
Sharlin
Unfortunately, you can't, at least not before the next version of the Standard (and its implementation in compilers...) but you *can* do the next best thing: a class template with a typedef inside (as the anonymous poster said, but better formatting ;):

template <typename T>struct SmartPtr{  typedef Loki::SmartPtr<   T,   Loki::RefCounted,    Loki::AllowConversion,   Loki::AssertCheck,   Loki::DefaultSPStorage> t;};


And then use it like:

SmartPtr<int>::t ptr(new int(123));


If you don't like the somewhat ugly syntax, another option would be to use inheritance the same way you already did, and write the necessary constructors and the assignment operator (these can just call the parent's corresponding methods and it should work).
SiCrane
SiCrane
If you want to get the inheritance mechanism to work, you need to implement the functions that don't get inherited. e.g.:
template <typename TYPE>class TSmartPtr : public Loki::SmartPtr  <     TYPE,    Loki::RefCounted,       // Our pointers will have reference counting    Loki::AllowConversion,  // Implicit conversion to contained pointer okay    Loki::AssertCheck,      // Assert checks requires    Loki::DefaultSPStorage  // Normal pointer-style storage  >{   typedef Loki::SmartPtr <      TYPE,     Loki::RefCounted,       // Our pointers will have reference counting     Loki::AllowConversion,  // Implicit conversion to contained pointer okay     Loki::AssertCheck,      // Assert checks requires     Loki::DefaultSPStorage  // Normal pointer-style storage    > BaseClass;  public:    TSmartPtr(TYPE * ptr) : BaseClass(ptr) {}      TSmartPtr & operator=(TYPE * rhs) {      BaseClass::operator=(rhs);      return *this;    }};
Murrgon
Murrgon
Beauty, that worked. I had to add a default constuctor as well, but after that it compiled.

Thanks everyone.
The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That''s funny ..."
Murrgon
Murrgon
Okay, I ran into another problem: operator==().

TSmartPtr<int> pInteger1;TSmartPtr<int> pInteger2;if (pInteger1 == pInteger2)  // Do something    


VC7.1 comes up with this wonder error:
error C2666: 'Loki::operator`=='' : 2 overloads have similar conversions.

I tried adding an operator==() to TSmartPtr that just calls the base class but it just gives me the same error.

Any suggestions?
The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" (I found it!) but "That''s funny ..."
SiCrane
SiCrane
I would punt to the GetImpl() function instead of the base class. e.g.:
template <typename T>bool operator==(const TSmartPtr<T> & lhs, const TSmartPtr<T> & rhs) {  return GetImpl(lhs) == GetImpl(rhs);}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.