+2001-06-18 Benjamin Kosnik <bkoz@redhat.com>
+
+ * include/bits/stl_raw_storage_iter.h: Format. Correct derivation.
+ * testsuite/20_util/raw_storage_iterator.cc: Same.
+
+ * include/bits/stl_alloc.h (_S_chunk_alloc): Change malloc to
+ operator new.
+ (__mem_interface): New typedef for switching between malloc and new.
+ * testsuite/20_util/allocator_members.cc: New file.
+
+ * testsuite/20_util/comparisons.cc: New file.
+ * testsuite/20_util/pairs.cc: New file.
+
2001-06-15 Phil Edwards <pme@sources.redhat.com>
* docs/html/documentation.html: Point to new doxygen'ed collection.
namespace std
{
-
-// Malloc-based allocator. Typically slower than default alloc below.
-// Typically thread-safe and more storage efficient.
-template <int __inst>
-class __malloc_alloc_template {
-
-private:
-
- static void* _S_oom_malloc(size_t);
- static void* _S_oom_realloc(void*, size_t);
- static void (* __malloc_alloc_oom_handler)();
-
-public:
-
- static void* allocate(size_t __n)
- {
- void* __result = malloc(__n);
- if (0 == __result) __result = _S_oom_malloc(__n);
- return __result;
- }
-
- static void deallocate(void* __p, size_t /* __n */)
- {
- free(__p);
- }
-
- static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
+ // A new-based allocator, as required by the standard.
+ class __new_alloc
{
- void* __result = realloc(__p, __new_sz);
- if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
- return __result;
- }
-
- static void (* __set_malloc_handler(void (*__f)()))()
- {
- void (* __old)() = __malloc_alloc_oom_handler;
- __malloc_alloc_oom_handler = __f;
- return(__old);
- }
-
-};
-
-// malloc_alloc out-of-memory handling
+ public:
+ static void*
+ allocate(size_t __n)
+ { return ::operator new(__n); }
+
+ static void
+ deallocate(void* __p, size_t)
+ { ::operator delete(__p); }
+ };
+
+ // Malloc-based allocator. Typically slower than default alloc below.
+ // Typically thread-safe and more storage efficient.
+ template <int __inst>
+ class __malloc_alloc_template
+ {
+ private:
+ static void* _S_oom_malloc(size_t);
+ static void* _S_oom_realloc(void*, size_t);
+ static void (* __malloc_alloc_oom_handler)();
+
+ public:
+ static void*
+ allocate(size_t __n)
+ {
+ void* __result = malloc(__n);
+ if (0 == __result) __result = _S_oom_malloc(__n);
+ return __result;
+ }
-template <int __inst>
-void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
+ static void
+ deallocate(void* __p, size_t /* __n */)
+ { free(__p); }
-template <int __inst>
-void*
-__malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
-{
- void (* __my_malloc_handler)();
- void* __result;
+ static void*
+ reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
+ {
+ void* __result = realloc(__p, __new_sz);
+ if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
+ return __result;
+ }
+
+ static void (* __set_malloc_handler(void (*__f)()))()
+ {
+ void (* __old)() = __malloc_alloc_oom_handler;
+ __malloc_alloc_oom_handler = __f;
+ return(__old);
+ }
+ };
- for (;;) {
- __my_malloc_handler = __malloc_alloc_oom_handler;
- if (0 == __my_malloc_handler) { std::__throw_bad_alloc(); }
- (*__my_malloc_handler)();
- __result = malloc(__n);
- if (__result) return(__result);
+ // malloc_alloc out-of-memory handling
+ template <int __inst>
+ void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
+
+ template <int __inst>
+ void*
+ __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
+ {
+ void (* __my_malloc_handler)();
+ void* __result;
+
+ for (;;)
+ {
+ __my_malloc_handler = __malloc_alloc_oom_handler;
+ if (0 == __my_malloc_handler)
+ std::__throw_bad_alloc();
+ (*__my_malloc_handler)();
+ __result = malloc(__n);
+ if (__result)
+ return(__result);
+ }
}
-}
-
-template <int __inst>
-void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
-{
- void (* __my_malloc_handler)();
- void* __result;
-
- for (;;) {
- __my_malloc_handler = __malloc_alloc_oom_handler;
- if (0 == __my_malloc_handler) { std::__throw_bad_alloc(); }
- (*__my_malloc_handler)();
- __result = realloc(__p, __n);
- if (__result) return(__result);
+
+ template <int __inst>
+ void*
+ __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
+ {
+ void (* __my_malloc_handler)();
+ void* __result;
+
+ for (;;)
+ {
+ __my_malloc_handler = __malloc_alloc_oom_handler;
+ if (0 == __my_malloc_handler)
+ std::__throw_bad_alloc();
+ (*__my_malloc_handler)();
+ __result = realloc(__p, __n);
+ if (__result)
+ return(__result);
+ }
}
-}
-typedef __malloc_alloc_template<0> malloc_alloc;
+ // Determines the underlying allocator choice.
+# ifdef __USE_MALLOC
+ typedef __malloc_alloc_template<0> __mem_interface;
+#else
+ typedef __new_alloc __mem_interface;
+#endif
template<class _Tp, class _Alloc>
class simple_alloc {
{
void* __ret = 0;
- if (__n > (size_t) _MAX_BYTES) {
- __ret = malloc_alloc::allocate(__n);
- }
- else {
- _Obj* __STL_VOLATILE* __my_free_list
- = _S_free_list + _S_freelist_index(__n);
- // Acquire the lock here with a constructor call.
- // This ensures that it is released in exit or during stack
- // unwinding.
+ if (__n > (size_t) _MAX_BYTES)
+ __ret = __mem_interface::allocate(__n);
+ else
+ {
+ _Obj* __STL_VOLATILE* __my_free_list = _S_free_list + _S_freelist_index(__n);
+ // Acquire the lock here with a constructor call.
+ // This ensures that it is released in exit or during stack
+ // unwinding.
# ifndef _NOTHREADS
- /*REFERENCED*/
- _Lock __lock_instance;
+ /*REFERENCED*/
+ _Lock __lock_instance;
# endif
- _Obj* __RESTRICT __result = *__my_free_list;
- if (__result == 0)
- __ret = _S_refill(_S_round_up(__n));
- else {
- *__my_free_list = __result -> _M_free_list_link;
- __ret = __result;
+ _Obj* __RESTRICT __result = *__my_free_list;
+ if (__result == 0)
+ __ret = _S_refill(_S_round_up(__n));
+ else
+ {
+ *__my_free_list = __result -> _M_free_list_link;
+ __ret = __result;
+ }
}
- }
-
+
return __ret;
};
static void deallocate(void* __p, size_t __n)
{
if (__n > (size_t) _MAX_BYTES)
- malloc_alloc::deallocate(__p, __n);
- else {
- _Obj* __STL_VOLATILE* __my_free_list
+ __mem_interface::deallocate(__p, __n);
+ else
+ {
+ _Obj* __STL_VOLATILE* __my_free_list
= _S_free_list + _S_freelist_index(__n);
- _Obj* __q = (_Obj*)__p;
-
- // acquire lock
+ _Obj* __q = (_Obj*)__p;
+
+ // acquire lock
# ifndef _NOTHREADS
- /*REFERENCED*/
- _Lock __lock_instance;
+ /*REFERENCED*/
+ _Lock __lock_instance;
# endif /* _NOTHREADS */
- __q -> _M_free_list_link = *__my_free_list;
- *__my_free_list = __q;
- // lock is released here
- }
+ __q -> _M_free_list_link = *__my_free_list;
+ *__my_free_list = __q;
+ // lock is released here
+ }
}
-
+
static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);
-
-} ;
+};
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
typedef __default_alloc_template<false, 0> single_client_alloc;
size_t __total_bytes = __size * __nobjs;
size_t __bytes_left = _S_end_free - _S_start_free;
- if (__bytes_left >= __total_bytes) {
+ if (__bytes_left >= __total_bytes)
+ {
__result = _S_start_free;
_S_start_free += __total_bytes;
return(__result);
- } else if (__bytes_left >= __size) {
+ }
+ else if (__bytes_left >= __size)
+ {
__nobjs = (int)(__bytes_left/__size);
__total_bytes = __size * __nobjs;
__result = _S_start_free;
_S_start_free += __total_bytes;
return(__result);
- } else {
+ }
+ else
+ {
size_t __bytes_to_get =
2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
// Try to make use of the left-over piece.
- if (__bytes_left > 0) {
- _Obj* __STL_VOLATILE* __my_free_list =
- _S_free_list + _S_freelist_index(__bytes_left);
-
- ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
- *__my_free_list = (_Obj*)_S_start_free;
- }
- _S_start_free = (char*)malloc(__bytes_to_get);
- if (0 == _S_start_free) {
+ if (__bytes_left > 0)
+ {
+ _Obj* __STL_VOLATILE* __my_free_list =
+ _S_free_list + _S_freelist_index(__bytes_left);
+
+ ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
+ *__my_free_list = (_Obj*)_S_start_free;
+ }
+ _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get);
+ if (0 == _S_start_free)
+ {
size_t __i;
_Obj* __STL_VOLATILE* __my_free_list;
_Obj* __p;
- // Try to make do with what we have. That can't
- // hurt. We do not try smaller requests, since that tends
- // to result in disaster on multi-process machines.
- for (__i = __size;
- __i <= (size_t) _MAX_BYTES;
- __i += (size_t) _ALIGN) {
+ // Try to make do with what we have. That can't hurt. We
+ // do not try smaller requests, since that tends to result
+ // in disaster on multi-process machines.
+ __i = __size;
+ for (; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN)
+ {
__my_free_list = _S_free_list + _S_freelist_index(__i);
__p = *__my_free_list;
- if (0 != __p) {
- *__my_free_list = __p -> _M_free_list_link;
- _S_start_free = (char*)__p;
+ if (0 != __p)
+ {
+ *__my_free_list = __p -> _M_free_list_link;
+ _S_start_free = (char*)__p;
_S_end_free = _S_start_free + __i;
return(_S_chunk_alloc(__size, __nobjs));
// Any leftover piece will eventually make it to the
// right free list.
- }
- }
+ }
+ }
_S_end_free = 0; // In case of exception.
- _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
+ _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get);
// This should either throw an
// exception or remedy the situation. Thus we assume it
// succeeded.
- }
+ }
_S_heap_size += __bytes_to_get;
_S_end_free = _S_start_free + __bytes_to_get;
return(_S_chunk_alloc(__size, __nobjs));
- }
+ }
}
namespace std
{
+ template <class _ForwardIterator, class _Tp>
+ class raw_storage_iterator
+ : public iterator<output_iterator_tag, void, void, void, void>
+ {
+ protected:
+ _ForwardIterator _M_iter;
-template <class _ForwardIterator, class _Tp>
-class raw_storage_iterator {
-protected:
- _ForwardIterator _M_iter;
-public:
- typedef output_iterator_tag iterator_category;
- typedef void value_type;
- typedef void difference_type;
- typedef void pointer;
- typedef void reference;
+ public:
+ explicit
+ raw_storage_iterator(_ForwardIterator __x) : _M_iter(__x) {}
- explicit raw_storage_iterator(_ForwardIterator __x) : _M_iter(__x) {}
- raw_storage_iterator& operator*() { return *this; }
- raw_storage_iterator& operator=(const _Tp& __element) {
- construct(&*_M_iter, __element);
- return *this;
- }
- raw_storage_iterator<_ForwardIterator, _Tp>& operator++() {
- ++_M_iter;
- return *this;
- }
- raw_storage_iterator<_ForwardIterator, _Tp> operator++(int) {
- raw_storage_iterator<_ForwardIterator, _Tp> __tmp = *this;
- ++_M_iter;
- return __tmp;
- }
-};
+ raw_storage_iterator&
+ operator*() { return *this; }
+ raw_storage_iterator&
+ operator=(const _Tp& __element)
+ {
+ construct(&*_M_iter, __element);
+ return *this;
+ }
+ raw_storage_iterator<_ForwardIterator, _Tp>&
+ operator++()
+ {
+ ++_M_iter;
+ return *this;
+ }
+
+ raw_storage_iterator<_ForwardIterator, _Tp>
+ operator++(int)
+ {
+ raw_storage_iterator<_ForwardIterator, _Tp> __tmp = *this;
+ ++_M_iter;
+ return __tmp;
+ }
+ };
} // namespace std
-#endif /* _CPP_BITS_STL_RAW_STORAGE_ITERATOR_H */
+#endif
// Local Variables:
// mode:C++
--- /dev/null
+// 2001-06-14 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 20.4.1.1 allocator members
+
+#include <memory>
+#include <cstdlib>
+#include <debug_assert.h>
+
+struct gnu { };
+
+bool check_new = false;
+bool check_delete = false;
+
+void*
+operator new(std::size_t n) throw(std::bad_alloc)
+{
+ check_new = true;
+ return std::malloc(n);
+}
+
+void operator delete(void *v) throw()
+{
+ check_delete = true;
+ return std::free(v);
+}
+
+int main(void)
+{
+ bool test = true;
+ std::allocator<gnu> obj;
+
+ // XXX These should work for various size allocation and
+ // deallocations. Currently, they only work as expected for sizes >
+ // _MAX_BYTES as defined in stl_alloc.h, which happes to be 128.
+ gnu* pobj = obj.allocate(256);
+ VERIFY( check_new );
+
+ obj.deallocate(pobj, 256);
+ VERIFY( check_delete );
+
+ return 0;
+}
--- /dev/null
+// 2001-06-18 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 20.3.3 Comparisons
+
+#include <functional>
+
+class gnu_obj
+{
+ int i;
+public:
+ gnu_obj(int arg = 0): i(arg) { }
+ bool operator==(const gnu_obj& rhs) const { return i == rhs.i; }
+ bool operator!=(const gnu_obj& rhs) const { return i != rhs.i; }
+ bool operator<(const gnu_obj& rhs) const { return i < rhs.i; }
+};
+
+template<typename T>
+ struct gnu_t
+ {
+ bool b;
+ public:
+ gnu_t(bool arg = 0): b(arg) { }
+ bool operator==(const gnu_t& rhs) const { return b == rhs.b; }
+ bool operator!=(const gnu_t& rhs) const { return b != rhs.b; }
+ bool operator<(const gnu_t& rhs) const { return b == rhs.b; }
+ };
+
+template struct std::not_equal_to<void*>;
+template struct std::not_equal_to<gnu_obj>;
+template struct std::not_equal_to<gnu_t<long> >;
+
+int main()
+{
+ return 0;
+}
--- /dev/null
+// 2001-06-18 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 20.2.2 Pairs
+
+#include <utility>
+#include <debug_assert.h>
+
+class gnu_obj
+{
+ int i;
+public:
+ gnu_obj(int arg = 0): i(arg) { }
+ bool operator==(const gnu_obj& rhs) const { return i == rhs.i; }
+ bool operator<(const gnu_obj& rhs) const { return i < rhs.i; }
+};
+
+template<typename T>
+ struct gnu_t
+ {
+ bool b;
+ public:
+ gnu_t(bool arg = 0): b(arg) { }
+ bool operator==(const gnu_t& rhs) const { return b == rhs.b; }
+ bool operator<(const gnu_t& rhs) const { return int(b) < int(rhs.b); }
+ };
+
+
+// heterogeneous
+void test01()
+{
+ bool test = true;
+
+ std::pair<bool, long> p_bl_1(true, 433);
+ std::pair<bool, long> p_bl_2 = std::make_pair(true, 433);
+ VERIFY( p_bl_1 == p_bl_2 );
+ VERIFY( !(p_bl_1 < p_bl_2) );
+
+ std::pair<const char*, float> p_sf_1("total enlightenment", 433.00);
+ std::pair<const char*, float> p_sf_2 = std::make_pair("total enlightenment",
+ 433.00);
+ VERIFY( p_sf_1 == p_sf_2 );
+ VERIFY( !(p_sf_1 < p_sf_2) );
+
+ std::pair<const char*, gnu_obj> p_sg_1("enlightenment", gnu_obj(5));
+ std::pair<const char*, gnu_obj> p_sg_2 = std::make_pair("enlightenment",
+ gnu_obj(5));
+ VERIFY( p_sg_1 == p_sg_2 );
+ VERIFY( !(p_sg_1 < p_sg_2) );
+
+ std::pair<gnu_t<long>, gnu_obj> p_st_1(gnu_t<long>(false), gnu_obj(5));
+ std::pair<gnu_t<long>, gnu_obj> p_st_2 = std::make_pair(gnu_t<long>(false),
+ gnu_obj(5));
+ VERIFY( p_st_1 == p_st_2 );
+ VERIFY( !(p_st_1 < p_st_2) );
+}
+
+// homogeneous
+void test02()
+{
+ bool test = true;
+
+ std::pair<bool, bool> p_bb_1(true, false);
+ std::pair<bool, bool> p_bb_2 = std::make_pair(true, false);
+ VERIFY( p_bb_1 == p_bb_2 );
+ VERIFY( !(p_bb_1 < p_bb_2) );
+}
+
+
+// const
+void test03()
+{
+ bool test = true;
+
+ const std::pair<bool, long> p_bl_1(true, 433);
+ const std::pair<bool, long> p_bl_2 = std::make_pair(true, 433);
+ VERIFY( p_bl_1 == p_bl_2 );
+ VERIFY( !(p_bl_1 < p_bl_2) );
+
+ const std::pair<const char*, float> p_sf_1("total enlightenment", 433.00);
+ const std::pair<const char*, float> p_sf_2 =
+ std::make_pair("total enlightenment", 433.00);
+ VERIFY( p_sf_1 == p_sf_2 );
+ VERIFY( !(p_sf_1 < p_sf_2) );
+
+ const std::pair<const char*, gnu_obj> p_sg_1("enlightenment", gnu_obj(5));
+ const std::pair<const char*, gnu_obj> p_sg_2 =
+ std::make_pair("enlightenment", gnu_obj(5));
+ VERIFY( p_sg_1 == p_sg_2 );
+ VERIFY( !(p_sg_1 < p_sg_2) );
+
+ const std::pair<gnu_t<long>, gnu_obj> p_st_1(gnu_t<long>(false), gnu_obj(5));
+ const std::pair<gnu_t<long>, gnu_obj> p_st_2 =
+ std::make_pair(gnu_t<long>(false), gnu_obj(5));
+ VERIFY( p_st_1 == p_st_2 );
+ VERIFY( !(p_st_1 < p_st_2) );
+}
+
+// const&
+void test04()
+{
+ bool test = true;
+ const gnu_obj& obj1 = gnu_obj(5);
+ const std::pair<const char*, gnu_obj> p_sg_1("enlightenment", obj1);
+ const std::pair<const char*, gnu_obj> p_sg_2 =
+ std::make_pair("enlightenment", obj1);
+ VERIFY( p_sg_1 == p_sg_2 );
+ VERIFY( !(p_sg_1 < p_sg_2) );
+
+ const gnu_t<long>& tmpl1 = gnu_t<long>(false);
+ const std::pair<gnu_t<long>, gnu_obj> p_st_1(tmpl1, obj1);
+ const std::pair<gnu_t<long>, gnu_obj> p_st_2 = std::make_pair(tmpl1, obj1);
+ VERIFY( p_st_1 == p_st_2 );
+ VERIFY( !(p_st_1 < p_st_2) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}
--- /dev/null
+// 2001-06-18 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+//
+// 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 20.4.2 raw storage iterator
+
+#include <memory>
+
+void test01()
+{
+ using namespace std;
+
+ // Check for required base class.
+ long l;
+ raw_storage_iterator<long*, long> rs_it(&l);
+ iterator<output_iterator_tag, void, void, void, void>* base = &rs_it;
+
+ // Check for required typedefs
+ typedef raw_storage_iterator<long*, long>::value_type value_type;
+ typedef raw_storage_iterator<long*, long>::difference_type difference_type;
+ typedef raw_storage_iterator<long*, long>::pointer pointer;
+ typedef raw_storage_iterator<long*, long>::reference reference;
+ typedef raw_storage_iterator<long*, long>::iterator_category iteratory_category;
+
+}
+
+int main()
+{
+ test01();
+ return 0;
+}