[GSoC] Extend shared_ptr to support arrays

Fan You youfan.noey@gmail.com
Mon Mar 16 19:14:00 GMT 2015


Hello,

It's my simple version of extending shared_ptr to support arrays, am I
in the right direction?

When I do the boundary checking, when user try to access elements that
are out of boundary, should I throw an exception or just use assert to
avoid that from happening? (I saw boost use BOOST_ASSERT to do that)

Next, my plan for GSoC is to finish shared_ptr_array_support first and
then choose one or two from other TS.

For those TS I am looking into:

- Invocation type traits
  I have a very limited compiler knowledge, so I am still learning it.

- Polymorphic Memory Resources
  After reading the proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3916.pdf>, I
am still not quite sure about the idea of Polymorphic memory
resources. The example on page 5 make sense to me, but what's the key
different between the original memory allocation method and this? Any
other resource that I can read from?

- Networking TS
  I get the wrong link last time, but I find it myself(don't know if
it's correct <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html>).
The proposal intend to implement a whole Network Library and it's
currently too big for me to read them all. Can you suggest a specific
part of it that I should start looking at or working on?


Is it OK and realistic to propose multiple TS in GSoC? Any suggestion
or critic are welcome!

Thanks,

Fan
-------------- next part --------------
diff --git a/bits/shared_ptr.h b/bits/shared_ptr.h
index 081d3bd..d5f6e1c 100644
--- a/bits/shared_ptr.h
+++ b/bits/shared_ptr.h
@@ -614,9 +614,182 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return std::hash<_Tp*>()(__s.get()); }
     };
 
-  // @} group pointer_abstractions
+	/// specialization for shared_ptr_array
 
-_GLIBCXX_END_NAMESPACE_VERSION
+	//dynamic size
+	template<typename _Tp>
+		class shared_ptr<_Tp[]> : public __shared_ptr<_Tp>{
+			public:
+				constexpr shared_ptr<_Tp[]>() noexcept :
+					__shared_ptr<_Tp>() { }
+
+				template<typename _Tp1>
+					explicit shared_ptr<_Tp[]>(_Tp1* __p) :
+						 __shared_ptr<_Tp>(__p, _A_Del) { }
+
+				template<typename _Tp1, typename _Deleter>
+					shared_ptr<_Tp[]>(_Tp1* __p, _Deleter __d) :
+						 __shared_ptr<_Tp>(__p, __d) { }
+
+				template<typename _Deleter>
+					shared_ptr<_Tp[]>(nullptr_t __p, _Deleter __d) :
+						 __shared_ptr<_Tp>(__p, __d) { }
+
+				template<typename _Tp1, typename _Deleter, typename _Alloc>
+					shared_ptr<_Tp[]>(_Tp1* __p, _Deleter __d, _Alloc __a):
+						__shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
+
+				template<typename _Deleter, typename _Alloc>
+					shared_ptr<_Tp[]>(nullptr_t __p, _Deleter __d, _Alloc __a):
+						__shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
+
+				template<typename _Tp1>
+					shared_ptr<_Tp[]>(const shared_ptr<_Tp1[]>& __r, _Tp* __p) noexcept :
+					__shared_ptr<_Tp>(__r, __p) { }
+
+				template<typename _Tp1, typename = typename
+					std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+					shared_ptr<_Tp[]>(const shared_ptr<_Tp1[]>& __r) noexcept :
+					__shared_ptr<_Tp>(__r) { }
+
+				shared_ptr<_Tp[]>(shared_ptr<_Tp[]>& __r) = default;
+
+				//shared_ptr<_Tp[]>(shared_ptr<_Tp[]>&& __r) noexcept :
+				//	__shared_ptr<_Tp>(std::move(__r)) { }
+
+				template<typename _Tp1, typename = typename
+					std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+					shared_ptr<_Tp[]>(shared_ptr<_Tp1[]>&& __r) noexcept
+					: __shared_ptr<_Tp>(std::move(__r)) { }
+
+#if _GLIBCXX_USE_DEPRECATED
+				template<typename _Tp1>
+					shared_ptr<_Tp[]>(std::auto_ptr<_Tp1>&& __r); // TODO auto_ptr still calls delete p;
+#endif
+
+				template<typename _Tp1, typename _Del>
+					shared_ptr<_Tp[]>(std::unique_ptr<_Tp1[], _Del>&& __r) :
+					__shared_ptr<_Tp>(std::move(__r)) { }
+
+				constexpr shared_ptr<_Tp[]>(nullptr_t __p) noexcept :
+					__shared_ptr<_Tp>(__p) { }
+
+#if _GLIBCXX_USE_DEPRECATED
+				//TODO
+#endif
+
+				shared_ptr<_Tp[]>& operator=(const shared_ptr<_Tp[]>&) noexcept = default;
+
+				template<typename _Tp1>
+					shared_ptr<_Tp[]>&
+					operator=(const shared_ptr<_Tp1[]>& __r) noexcept {
+						this->__shared_ptr<_Tp>::operator=(__r); 
+						return *this;
+					}
+
+				shared_ptr<_Tp[]>&
+					operator=(shared_ptr<_Tp[]>&& __r) noexcept
+					{
+						this->__shared_ptr<_Tp>::operator=(std::move(__r));
+						return *this;
+					}
+
+				template<typename _Tp1, typename _Del>
+					shared_ptr<_Tp[]>&
+					operator=(std::unique_ptr<_Tp1[], _Del>&& __r)
+					{
+						this->__shared_ptr<_Tp>::operator=(std::move(__r));
+						return *this;
+					}
+
+				// access element in array
+				typename std::add_lvalue_reference<_Tp>::type
+				operator[](size_t __i) const{
+					return (this->get())[__i];
+				}
+
+			protected:
+				struct _Deleter {
+					void operator()(_Tp const *p) {
+						delete [] p;
+					}
+				};
+
+			private:
+				_Deleter _A_Del;
+		};
+
+	// fix size TODO
+	template<typename _Tp, std::size_t _num>
+		class shared_ptr<_Tp[_num]> : public shared_ptr<_Tp[]> {
+			public:
+				constexpr shared_ptr<_Tp[_num]>() noexcept :
+					shared_ptr<_Tp[]>() { }
+
+				template<typename _Tp1>
+					explicit shared_ptr<_Tp[_num]>(_Tp1* __p) :
+						shared_ptr<_Tp[]>(__p) { }
+
+				template<typename _Tp1, typename _Deleter>
+					shared_ptr<_Tp[_num]>(_Tp1* __p, _Deleter __d) :
+						 shared_ptr<_Tp[]>(__p, __d) { }
+
+				template<typename _Deleter>
+					shared_ptr<_Tp[_num]>(nullptr_t __p, _Deleter __d) :
+						 shared_ptr<_Tp[]>(__p, __d) { }
+
+				template<typename _Tp1, typename _Deleter, typename _Alloc>
+					shared_ptr<_Tp[_num]>(_Tp1* __p, _Deleter __d, _Alloc __a):
+						shared_ptr<_Tp[]>(__p, __d, std::move(__a)) { }
+
+				template<typename _Deleter, typename _Alloc>
+					shared_ptr<_Tp[_num]>(nullptr_t __p, _Deleter __d, _Alloc __a):
+						shared_ptr<_Tp[]>(__p, __d, std::move(__a)) { }
+
+				template<typename _Tp1>
+					shared_ptr<_Tp[_num]>(const shared_ptr<_Tp1[_num]>& __r, _Tp* __p) noexcept : // or _Tp1[]
+					shared_ptr<_Tp[]>(__r, __p) { }
+
+				template<typename _Tp1, typename = typename
+					std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+					shared_ptr<_Tp[_num]>(const shared_ptr<_Tp1[_num]>& __r) noexcept : // or _Tp1[]
+					shared_ptr<_Tp[]>(__r) { }
+
+				shared_ptr<_Tp[_num]>(shared_ptr<_Tp[_num]>& __r) = default; // or _Tp1[]
+
+				//shared_ptr<_Tp[_num]>(shared_ptr<_Tp[_num]>&& __r) noexcept :
+				//	__shared_ptr<_Tp>(std::move(__r)) { }
+
+				template<typename _Tp1, typename = typename
+					std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+					shared_ptr<_Tp[_num]>(shared_ptr<_Tp1[]>&& __r) noexcept // or _Tp1[]
+					: shared_ptr<_Tp[]>(std::move(__r)) { }
+
+#if _GLIBCXX_USE_DEPRECATED
+				template<typename _Tp1>
+					shared_ptr<_Tp[_num]>(std::auto_ptr<_Tp1>&& __r); // TODO auto_ptr still calls delete p;
+#endif
+
+				template<typename _Tp1, typename _Del>
+					shared_ptr<_Tp[_num]>(std::unique_ptr<_Tp1[], _Del>&& __r) :
+					shared_ptr<_Tp[]>(std::move(__r)) { }
+
+				constexpr shared_ptr<_Tp[_num]>(nullptr_t __p) noexcept :
+					shared_ptr<_Tp[]>(__p) { }
+
+				typename std::add_lvalue_reference<_Tp>::type
+				operator[](size_t __i) const{
+					if(__i >= _num) {
+						throw;
+					}else {
+						return (this->get())[__i];
+					}
+				}
+		};
+
+	// @} group pointer_abstractions
+
+	_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #endif // _SHARED_PTR_H


More information about the Libstdc++ mailing list