diff options
author | pme <pme@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-03 22:25:06 +0000 |
---|---|---|
committer | pme <pme@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-07-03 22:25:06 +0000 |
commit | 72bbf3f4de70e90c6447ba2807e328d24cff650c (patch) | |
tree | 4b4d1c65ed92465eddeca39b31b0fb0d749d3f6a | |
parent | 3c63774df8720dd4251b7479b5dd2e1f6a5c48c2 (diff) | |
download | gcc-72bbf3f4de70e90c6447ba2807e328d24cff650c.tar.gz |
2002-07-03 Jack Reeves <jackw_reeves@hotmail.com>
Kenny Simpson <theonetruekenny@yahoo.com>
Phil Edwards <pme@gcc.gnu.org>
PR libstdc++/3946
* testsuite/20_util/auto_ptr.cc (test08): New test.
* include/std/std_memory.h (auto_ref_ptr): Make constructor explicit.
(auto_ptr::operator auto_ptr_ref): Fix typo.
General reformatting and doxygenating of the whole file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55223 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 10 | ||||
-rw-r--r-- | libstdc++-v3/include/std/std_memory.h | 373 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/auto_ptr.cc | 18 |
3 files changed, 297 insertions, 104 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 623580609a1..adbf06b173d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2002-07-03 Jack Reeves <jackw_reeves@hotmail.com> + Kenny Simpson <theonetruekenny@yahoo.com> + Phil Edwards <pme@gcc.gnu.org> + + PR libstdc++/3946 + * testsuite/20_util/auto_ptr.cc (test08): New test. + * include/std/std_memory.h (auto_ref_ptr): Make constructor explicit. + (auto_ptr::operator auto_ptr_ref): Fix typo. + General reformatting and doxygenating of the whole file. + 2002-07-03 Benjamin Kosnik <bkoz@redhat.com> PR libstdc++/7097 diff --git a/libstdc++-v3/include/std/std_memory.h b/libstdc++-v3/include/std/std_memory.h index b7feb37aa45..5850eb2a007 100644 --- a/libstdc++-v3/include/std/std_memory.h +++ b/libstdc++-v3/include/std/std_memory.h @@ -58,147 +58,314 @@ #include <bits/stl_uninitialized.h> #include <bits/stl_raw_storage_iter.h> +// Since this entire file is within namespace std, there's no reason to +// waste two spaces along the left column. Thus the leading indentation is +// slightly violated from here on. namespace std { +/** + * @if maint + * This is a helper function. The unused second parameter exists to + * permit the real get_temporary_buffer to use template parameter deduction. + * + * XXX This should perhaps use the pool. + * @endif +*/ +template <typename _Tp> +pair<_Tp*, ptrdiff_t> +__get_temporary_buffer(ptrdiff_t __len, _Tp*) +{ + if (__len > ptrdiff_t(INT_MAX / sizeof(_Tp))) + __len = INT_MAX / sizeof(_Tp); - /** - * @if maint - * This is a helper function. The unused second parameter exists to - * permit the real get_temporary_buffer to use template parameter deduction. - * @endif - */ - template <class _Tp> - pair<_Tp*, ptrdiff_t> - __get_temporary_buffer(ptrdiff_t __len, _Tp*) - { - if (__len > ptrdiff_t(INT_MAX / sizeof(_Tp))) - __len = INT_MAX / sizeof(_Tp); - - while (__len > 0) { - _Tp* __tmp = (_Tp*) std::malloc((std::size_t)__len * sizeof(_Tp)); - if (__tmp != 0) - return pair<_Tp*, ptrdiff_t>(__tmp, __len); - __len /= 2; - } - - return pair<_Tp*, ptrdiff_t>((_Tp*)0, 0); + while (__len > 0) { + _Tp* __tmp = (_Tp*) std::malloc((std::size_t)__len * sizeof(_Tp)); + if (__tmp != 0) + return pair<_Tp*, ptrdiff_t>(__tmp, __len); + __len /= 2; } - /** - * @brief This is a mostly-useless wrapper around malloc(). - * @param len The number of objects of type Tp. - * @return See full description. - * - * Reinventing the wheel, but this time with prettier spokes! - * - * This function tries to obtain storage for @c len adjacent Tp objects. - * The objects themselves are not constructed, of course. A pair<> is - * returned containing "the buffer s address and capacity (in the units of - * sizeof(Tp)), or a pair of 0 values if no storage can be obtained." - * Note that the capacity obtained may be less than that requested if the - * memory is unavailable; you should compare len with the .second return - * value. - */ - template <class _Tp> - inline pair<_Tp*, ptrdiff_t> get_temporary_buffer(ptrdiff_t __len) { + return pair<_Tp*, ptrdiff_t>((_Tp*)0, 0); +} + +/** + * @brief This is a mostly-useless wrapper around malloc(). + * @param len The number of objects of type Tp. + * @return See full description. + * + * Reinventing the wheel, but this time with prettier spokes! + * + * This function tries to obtain storage for @c len adjacent Tp objects. + * The objects themselves are not constructed, of course. A pair<> is + * returned containing "the buffer s address and capacity (in the units of + * sizeof(Tp)), or a pair of 0 values if no storage can be obtained." + * Note that the capacity obtained may be less than that requested if the + * memory is unavailable; you should compare len with the .second return + * value. +*/ +template<typename _Tp> + inline pair<_Tp*,ptrdiff_t> + get_temporary_buffer(ptrdiff_t __len) + { return __get_temporary_buffer(__len, (_Tp*) 0); } - /** - * @brief The companion to get_temporary_buffer(). - * @param p A buffer previously allocated by get_temporary_buffer. - * @return None. - * - * Frees the memory pointed to by p. - */ - template <class _Tp> - void return_temporary_buffer(_Tp* __p) { +/** + * @brief The companion to get_temporary_buffer(). + * @param p A buffer previously allocated by get_temporary_buffer. + * @return None. + * + * Frees the memory pointed to by p. + */ +template<typename _Tp> + void + return_temporary_buffer(_Tp* __p) + { std::free(__p); } -template <class _Tp1> +/** + * A wrapper class to provide auto_ptr with reference semantics. For + * example, an auto_ptr can be assigned (or constructed from) the result of + * a function which returns an auto_ptr by value. + * + * All the auto_ptr_ref stuff should happen behind the scenes. +*/ +template<typename _Tp1> struct auto_ptr_ref { _Tp1* _M_ptr; - auto_ptr_ref(_Tp1* __p) : _M_ptr(__p) {} + + explicit + auto_ptr_ref(_Tp1* __p) + : _M_ptr(__p) {} }; + /** - * A simple smart pointer providing strict ownership semantics. (More later.) + * @brief A simple smart pointer providing strict ownership semantics. + * + * The Standard says: + * <pre> + * An @c auto_ptr owns the object it holds a pointer to. Copying an + * @c auto_ptr copies the pointer and transfers ownership to the destination. + * If more than one @c auto_ptr owns the same object at the same time the + * behavior of the program is undefined. + * + * The uses of @c auto_ptr include providing temporary exception-safety for + * dynamically allocated memory, passing ownership of dynamically allocated + * memory to a function, and returning dynamically allocated memory from a + * function. @c auto_ptr does not meet the CopyConstructible and Assignable + * requirements for Standard Library <a href="tables.html#65">container</a> + * elements and thus instantiating a Standard Library container with an + * @c auto_ptr results in undefined behavior. + * </pre> + * Quoted from [20.4.5]/3. + * + * Good examples of what can and cannot be done with auto_ptr can be found + * in the libstdc++ testsuite. + * + * @if maint + * _GLIBCPP_RESOLVE_LIB_DEFECTS + * 127. auto_ptr<> conversion issues + * These resolutions have all been incorporated. + * @endif */ -template <class _Tp> +template<typename _Tp> class auto_ptr { private: _Tp* _M_ptr; public: + /// The pointed-to type. typedef _Tp element_type; - explicit auto_ptr(_Tp* __p = 0) throw() : _M_ptr(__p) {} - auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) {} + /** + * @brief An %auto_ptr is usually constructed from a raw pointer. + * @param p A pointer (defaults to NULL). + * + * This object now @e owns the object pointed to by @a p. + */ + explicit + auto_ptr(element_type* __p = 0) throw() + : _M_ptr(__p) { } - template <class _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() - : _M_ptr(__a.release()) {} + /** + * @brief An %auto_ptr can be constructed from another %auto_ptr. + * @param a Another %auto_ptr of the same type. + * + * This object now @e owns the object previously owned by @a a, which has + * given up ownsership. + */ + auto_ptr(auto_ptr& __a) throw() + : _M_ptr(__a.release()) { } - auto_ptr& operator=(auto_ptr& __a) throw() { - reset(__a.release()); - return *this; - } + /** + * @brief An %auto_ptr can be constructed from another %auto_ptr. + * @param a Another %auto_ptr of a different but related type. + * + * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type. + * + * This object now @e owns the object previously owned by @a a, which has + * given up ownsership. + */ + template<typename _Tp1> + auto_ptr(auto_ptr<_Tp1>& __a) throw() + : _M_ptr(__a.release()) { } - template <class _Tp1> - auto_ptr& operator=(auto_ptr<_Tp1>& __a) throw() { - reset(__a.release()); - return *this; - } - - // Note: The C++ standard says there is supposed to be an empty throw - // specification here, but omitting it is standard conforming. Its - // presence can be detected only if _Tp::~_Tp() throws, but (17.4.3.6/2) - // this is prohibited. + /** + * @brief %auto_ptr assignment operator. + * @param a Another %auto_ptr of the same type. + * + * This object now @e owns the object previously owned by @a a, which has + * given up ownsership. The object that this one @e used to own and + * track has been deleted. + */ + auto_ptr& + operator=(auto_ptr& __a) throw() + { + reset(__a.release()); + return *this; + } + + /** + * @brief %auto_ptr assignment operator. + * @param a Another %auto_ptr of a different but related type. + * + * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type. + * + * This object now @e owns the object previously owned by @a a, which has + * given up ownsership. The object that this one @e used to own and + * track has been deleted. + */ + template <typename _Tp1> + auto_ptr& + operator=(auto_ptr<_Tp1>& __a) throw() + { + reset(__a.release()); + return *this; + } + + /** + * When the %auto_ptr goes out of scope, the object it owns is deleted. + * If it no longer owns anything (i.e., @c get() is @c NULL), then this + * has no effect. + * + * @if maint + * The C++ standard says there is supposed to be an empty throw + * specification here, but omitting it is standard conforming. Its + * presence can be detected only if _Tp::~_Tp() throws, but this is + * prohibited. [17.4.3.6]/2 + * @end maint + */ ~auto_ptr() { delete _M_ptr; } - - _Tp& operator*() const throw() { - return *_M_ptr; - } - _Tp* operator->() const throw() { - return _M_ptr; - } - _Tp* get() const throw() { - return _M_ptr; - } - _Tp* release() throw() { - _Tp* __tmp = _M_ptr; - _M_ptr = 0; - return __tmp; - } - void reset(_Tp* __p = 0) throw() { - if (__p != _M_ptr) { - delete _M_ptr; - _M_ptr = __p; - } - } -public: - auto_ptr(auto_ptr_ref<_Tp> __ref) throw() + /** + * @brief Smart pointer dereferencing. + * + * If this %auto_ptr no longer owns anything, then this operation will + * crash. (For a smart pointer, "no longer owns anything" is the same as + * being a null pointer, and you know what happens when you dereference + * one of those...) + */ + element_type& + operator*() const throw() { return *_M_ptr; } + + /** + * @brief Smart pointer dereferencing. + * + * This returns the pointer itself, which the language then will + * automatically cause to be dereferenced. + */ + element_type* + operator->() const throw() { return _M_ptr; } + + /** + * @brief Bypassing the smart pointer. + * @return The raw pointer being managed. + * + * You can get a copy of the pointer that this object owns, for + * situations such as passing to a function which only accepts a raw + * pointer. + * + * @note This %auto_ptr still owns the memory. + */ + element_type* + get() const throw() { return _M_ptr; } + + /** + * @brief Bypassing the smart pointer. + * @return The raw pointer being managed. + * + * You can get a copy of the pointer that this object owns, for + * situations such as passing to a function which only accepts a raw + * pointer. + * + * @note This %auto_ptr no longer owns the memory. When this object + * goes out of scope, nothing will happen. + */ + element_type* + release() throw() + { + element_type* __tmp = _M_ptr; + _M_ptr = 0; + return __tmp; + } + + /** + * @brief Forcibly deletes the managed object. + * @param p A pointer (defaults to NULL). + * + * This object now @e owns the object pointed to by @a p. The previous + * object has been deleted. + */ + void + reset(element_type* __p = 0) throw() + { + if (__p != _M_ptr) + { + delete _M_ptr; + _M_ptr = __p; + } + } + + /** @{ + * @brief Automatic conversions + * + * These operations convert an %auto_ptr into and from an auto_ptr_ref + * automatically as needed. This allows constructs such as + * @code + * auto_ptr<Derived> func_returning_auto_ptr(.....); + * ... + * auto_ptr<Base> ptr = func_returning_auto_ptr(.....); + * @endcode + */ + auto_ptr(auto_ptr_ref<element_type> __ref) throw() : _M_ptr(__ref._M_ptr) {} - auto_ptr& operator=(auto_ptr_ref<_Tp> __ref) throw() { - if (__ref._M_ptr != this->get()) { - delete _M_ptr; - _M_ptr = __ref._M_ptr; + auto_ptr& + operator=(auto_ptr_ref<element_type> __ref) throw() + { + if (__ref._M_ptr != this->get()) + { + delete _M_ptr; + _M_ptr = __ref._M_ptr; + } + return *this; } - return *this; - } - template <class _Tp1> operator auto_ptr_ref<_Tp1>() throw() - { return auto_ptr_ref<_Tp>(this->release()); } - template <class _Tp1> operator auto_ptr<_Tp1>() throw() - { return auto_ptr<_Tp1>(this->release()); } + template<typename _Tp1> + operator auto_ptr_ref<_Tp1>() throw() + { return auto_ptr_ref<_Tp1>(this->release()); } + + template<typename _Tp1> + operator auto_ptr<_Tp1>() throw() + { return auto_ptr<_Tp1>(this->release()); } + /** @} */ }; } // namespace std #endif /* _CPP_MEMORY */ - diff --git a/libstdc++-v3/testsuite/20_util/auto_ptr.cc b/libstdc++-v3/testsuite/20_util/auto_ptr.cc index a1c3de2374e..cf0d37bfb78 100644 --- a/libstdc++-v3/testsuite/20_util/auto_ptr.cc +++ b/libstdc++-v3/testsuite/20_util/auto_ptr.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2000 Free Software Foundation +// Copyright (C) 2000, 2002 Free Software Foundation // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -276,6 +276,21 @@ test07() return 0; } + +// http://gcc.gnu.org/ml/libstdc++/2002-07/msg00024.html +struct Base{}; +struct Derived : public Base {}; +std::auto_ptr<Derived> conversiontest08() + { return std::auto_ptr<Derived>(new Derived); } + +void +test08() +{ + std::auto_ptr<Base> ptr; + ptr = conversiontest08(); +} + + int main() { @@ -286,6 +301,7 @@ main() test05(); test06(); test07(); + test08(); return 0; } |