aMule Forum

English => Compilation problems => Topic started by: Stu Redman on December 27, 2010, 10:16:49 PM

Title: Fun with templates
Post by: Stu Redman on December 27, 2010, 10:16:49 PM
The following compiles and runs fine with MSVC:
Code: [Select]
Index: ScopedPtr.h
===================================================================
--- ScopedPtr.h (revision 10416)
+++ ScopedPtr.h (working copy)
@@ -26,6 +26,7 @@
 #ifndef SCOPEDPTR_H
 #define SCOPEDPTR_H
 
+#include "OtherFunctions.h" // Needed for DeleteContents()
 
 /**
  * CScopedPtr is a simple smart pointer.
@@ -68,7 +69,7 @@
  return ptr;
  }
 
-private:
+protected:
  //@{
  //! A scoped pointer is neither copyable, nor assignable.
  CScopedPtr(const CScopedPtr<TYPE>&);
@@ -132,5 +133,25 @@
  TYPE* m_ptr;
 };
 
+
+template <typename STL_CONTAINER>
+class CScopedContainer : public CScopedPtr<STL_CONTAINER>
+{
+
+public:
+ /** Constructor. Note that CScopedContainer takes ownership of the array. */
+ CScopedContainer(STL_CONTAINER* ptr = 0)
+ : CScopedPtr(ptr)
+ {}
+
+ ~CScopedContainer()
+ {
+ if (m_ptr) {
+ DeleteContents(*m_ptr);
+ }
+ // m_ptr itself is deleted in base class
+ }
+};
+
 #endif // SCOPEDPTR_H
 // File_checked_for_headers
but GCC barfs at it:
Code: [Select]
In file included from ../../../../trunk/src/utils/fileview/../../SafeFile.cpp:29:0:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h: In constructor ‘CScopedContainer<STL_CONTAINER>::CScopedContainer(STL_CONTAINER*)’:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h:144:5: error: class ‘CScopedContainer<STL_CONTAINER>’ does not have any field named ‘CScopedPtr’
../../../../trunk/src/utils/fileview/../../ScopedPtr.h: In destructor ‘CScopedContainer<STL_CONTAINER>::~CScopedContainer()’:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h:149:7: error: ‘m_ptr’ was not declared in this scope
make[4]: *** [mulefileview-SafeFile.o] Error 1
Is it just me or is this more complicated?
Title: Re: Fun with templates
Post by: GonoszTopi on December 29, 2010, 02:24:20 PM
Yes, it's a bit more complicated.

Code: [Select]
In file included from ../../../../trunk/src/utils/fileview/../../SafeFile.cpp:29:0:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h: In constructor ‘CScopedContainer<STL_CONTAINER>::CScopedContainer(STL_CONTAINER*)’:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h:144:5: error: class ‘CScopedContainer<STL_CONTAINER>’ does not have any field named ‘CScopedPtr’
‘CScopedPtr’ and ‘CScopedPtr<STL_CONTAINER>’ are different classes names, and since we're deriving from the second, the first is unknown to the compiler. Just consider, that you're allowed to derive from both ‘CScopedPtr<A>’ and ‘CScopedPtr<B>’. Then which one should ‘CScopedPtr’ refer?

Code: [Select]
../../../../trunk/src/utils/fileview/../../ScopedPtr.h: In destructor ‘CScopedContainer<STL_CONTAINER>::~CScopedContainer()’:
../../../../trunk/src/utils/fileview/../../ScopedPtr.h:149:7: error: ‘m_ptr’ was not declared in this scope
Regarding templates, the compiler binds unqualified names at parse time instead of instatiation time (and does it right according to the C++ standard). Since ‘m_ptr’ is an unqualified name in this context, it tries to bind it when parsing the template. But since it is defined in the base class (which itself is also a template), the name is not yet known. You have to qualify the name with either ‘this->’ or ‘CScopedPtr<STL_CONTAINER>::’ to make the name binding happen at instantiation time.

To fix these issues:
Code: [Select]
diff --git a/src/ScopedPtr.h b/src/ScopedPtr.h
index d1fdab2..b3ae431 100644
--- a/src/ScopedPtr.h
+++ b/src/ScopedPtr.h
@@ -141,13 +141,13 @@ class CScopedContainer : public CScopedPtr<STL_CONTAINER>
 public:
        /** Constructor. Note that CScopedContainer takes ownership of the array. */
        CScopedContainer(STL_CONTAINER* ptr = 0)
-               : CScopedPtr(ptr)
+               : CScopedPtr<STL_CONTAINER>(ptr)
        {}
 
        ~CScopedContainer()
        {
-               if (m_ptr) {
-                       DeleteContents(*m_ptr);
+               if (this->m_ptr) {
+                       DeleteContents(*(this->m_ptr));
                }
                // m_ptr itself is deleted in base class
        }
Title: Re: Fun with templates
Post by: Stu Redman on December 29, 2010, 03:21:26 PM
Thank you, very well explained!
Strange though how MSVC implements kind of a different C++...