stl_pair.h (piecewise_construct_t, [...]): Add.
2010-04-30 Paolo Carlini <paolo.carlini@oracle.com> * include/bits/stl_pair.h (piecewise_construct_t, pair<>::pair(piecewise_construct_t, tuple, tuple)): Add. (pair<>::__cons, pair<>::__do_cons): Declare. (__decay_and_strip, __strip_reference_wrapper): Move... * include/std/type_traits: ... here. * include/std/functional (_Index_tuple, _Build_index_tuple): Move... * include/std/tuple: ... here. (pack_arguments): Add. (pair<>::__cons, pair<>::__do_cons): Define. * testsuite/20_util/tuple/creation_functions/pack_arguments.cc: New. * testsuite/20_util/pair/piecewise.cc: Likewise. * testsuite/20_util/tuple/cons/big_tuples.cc: Include <utility>. * testsuite/20_util/tuple/cons/constructor.cc: Likewise. * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust dg-error line numbers. * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise. * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. From-SVN: r158928
This commit is contained in:
parent
41700fc33b
commit
5e108459ec
12 changed files with 326 additions and 65 deletions
|
@ -1,3 +1,24 @@
|
|||
2010-04-30 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
* include/bits/stl_pair.h (piecewise_construct_t,
|
||||
pair<>::pair(piecewise_construct_t, tuple, tuple)): Add.
|
||||
(pair<>::__cons, pair<>::__do_cons): Declare.
|
||||
(__decay_and_strip, __strip_reference_wrapper): Move...
|
||||
* include/std/type_traits: ... here.
|
||||
* include/std/functional (_Index_tuple, _Build_index_tuple): Move...
|
||||
* include/std/tuple: ... here.
|
||||
(pack_arguments): Add.
|
||||
(pair<>::__cons, pair<>::__do_cons): Define.
|
||||
* testsuite/20_util/tuple/creation_functions/pack_arguments.cc: New.
|
||||
* testsuite/20_util/pair/piecewise.cc: Likewise.
|
||||
* testsuite/20_util/tuple/cons/big_tuples.cc: Include <utility>.
|
||||
* testsuite/20_util/tuple/cons/constructor.cc: Likewise.
|
||||
* testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust
|
||||
dg-error line numbers.
|
||||
* testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
|
||||
Likewise.
|
||||
* testsuite/20_util/declval/requirements/1_neg.cc: Likewise.
|
||||
|
||||
2010-04-27 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
||||
PR libstdc++/43865
|
||||
|
|
|
@ -57,15 +57,25 @@
|
|||
#ifndef _STL_PAIR_H
|
||||
#define _STL_PAIR_H 1
|
||||
|
||||
#include <bits/move.h> // for std::move / std::forward, std::decay, and
|
||||
// std::swap
|
||||
#include <bits/move.h> // for std::move / std::forward, and std::swap
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
#include <type_traits>
|
||||
#include <type_traits> // for std::__decay_and_strip too
|
||||
#endif
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
struct piecewise_construct_t { };
|
||||
|
||||
// forward declarations
|
||||
template<typename...>
|
||||
class tuple;
|
||||
|
||||
template<int...>
|
||||
struct _Index_tuple;
|
||||
#endif
|
||||
|
||||
/// pair holds two objects of arbitrary type.
|
||||
template<class _T1, class _T2>
|
||||
struct pair
|
||||
|
@ -111,6 +121,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
|||
pair(pair&& __p)
|
||||
: first(std::move(__p.first)),
|
||||
second(std::move(__p.second)) { }
|
||||
|
||||
template<class... _Args1, class... _Args2>
|
||||
pair(piecewise_construct_t,
|
||||
tuple<_Args1...> __first_args,
|
||||
tuple<_Args2...> __second_args)
|
||||
: first(__cons<first_type>(std::move(__first_args))),
|
||||
second(__cons<second_type>(std::move(__second_args))) { }
|
||||
#endif
|
||||
|
||||
/** There is also a templated copy ctor for the @c pair class itself. */
|
||||
|
@ -149,6 +166,15 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
|||
swap(first, __p.first);
|
||||
swap(second, __p.second);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename _Tp, typename... _Args>
|
||||
static _Tp
|
||||
__cons(tuple<_Args...>&&);
|
||||
|
||||
template<typename _Tp, typename... _Args, int... _Indexes>
|
||||
static _Tp
|
||||
__do_cons(tuple<_Args...>&&, const _Index_tuple<_Indexes...>&);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -217,35 +243,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
|||
make_pair(_T1 __x, _T2 __y)
|
||||
{ return pair<_T1, _T2>(__x, __y); }
|
||||
#else
|
||||
template<typename _Tp>
|
||||
class reference_wrapper;
|
||||
|
||||
// Helper which adds a reference to a type when given a reference_wrapper
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper
|
||||
{
|
||||
typedef _Tp __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper<reference_wrapper<_Tp> >
|
||||
{
|
||||
typedef _Tp& __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper<const reference_wrapper<_Tp> >
|
||||
{
|
||||
typedef _Tp& __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __decay_and_strip
|
||||
{
|
||||
typedef typename __strip_reference_wrapper<
|
||||
typename decay<_Tp>::type>::__type __type;
|
||||
};
|
||||
|
||||
// NB: DR 706.
|
||||
template<class _T1, class _T2>
|
||||
inline pair<typename __decay_and_strip<_T1>::__type,
|
||||
|
|
|
@ -857,29 +857,6 @@ namespace std
|
|||
: public integral_constant<int, _Num>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* Stores a tuple of indices. Used by bind() to extract the elements
|
||||
* in a tuple.
|
||||
*/
|
||||
template<int... _Indexes>
|
||||
struct _Index_tuple
|
||||
{
|
||||
typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
|
||||
};
|
||||
|
||||
/// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
|
||||
template<std::size_t _Num>
|
||||
struct _Build_index_tuple
|
||||
{
|
||||
typedef typename _Build_index_tuple<_Num-1>::__type::__next __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _Build_index_tuple<0>
|
||||
{
|
||||
typedef _Index_tuple<> __type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by _Safe_tuple_element to indicate that there is no tuple
|
||||
* element at this position.
|
||||
|
|
|
@ -550,6 +550,28 @@ namespace std
|
|||
return __result_type(std::forward<_Elements>(__args)...);
|
||||
}
|
||||
|
||||
template<typename _Tp, bool = is_array<_Tp>::value>
|
||||
struct __pa_add_rvalue_reference_helper
|
||||
{ typedef typename std::add_rvalue_reference<_Tp>::type __type; };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __pa_add_rvalue_reference_helper<_Tp, true>
|
||||
{ typedef _Tp& __type; };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __pa_add_rvalue_reference
|
||||
: public __pa_add_rvalue_reference_helper<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename... _Elements>
|
||||
inline tuple<typename __pa_add_rvalue_reference<_Elements>::__type...>
|
||||
pack_arguments(_Elements&&... __args)
|
||||
{
|
||||
typedef tuple<typename __pa_add_rvalue_reference<_Elements>::__type...>
|
||||
__result_type;
|
||||
return __result_type(std::forward<_Elements>(__args)...);
|
||||
}
|
||||
|
||||
template<std::size_t...> struct __index_holder { };
|
||||
|
||||
template<std::size_t __i, typename _IdxHolder, typename... _Elements>
|
||||
|
@ -678,6 +700,49 @@ namespace std
|
|||
{
|
||||
_Swallow_assign ignore;
|
||||
}; // anonymous namespace
|
||||
|
||||
/**
|
||||
* Stores a tuple of indices. Used by bind() to extract the elements
|
||||
* in a tuple.
|
||||
*/
|
||||
template<int... _Indexes>
|
||||
struct _Index_tuple
|
||||
{
|
||||
typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
|
||||
};
|
||||
|
||||
/// Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
|
||||
template<std::size_t _Num>
|
||||
struct _Build_index_tuple
|
||||
{
|
||||
typedef typename _Build_index_tuple<_Num-1>::__type::__next __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _Build_index_tuple<0>
|
||||
{
|
||||
typedef _Index_tuple<> __type;
|
||||
};
|
||||
|
||||
// See stl_pair.h...
|
||||
template<class _T1, class _T2>
|
||||
template<typename _Tp, typename... _Args>
|
||||
inline _Tp
|
||||
pair<_T1, _T2>::
|
||||
__cons(tuple<_Args...>&& __tuple)
|
||||
{
|
||||
typedef typename _Build_index_tuple<sizeof...(_Args)>::__type
|
||||
_Indexes;
|
||||
return __do_cons<_Tp>(std::move(__tuple), _Indexes());
|
||||
}
|
||||
|
||||
template<class _T1, class _T2>
|
||||
template<typename _Tp, typename... _Args, int... _Indexes>
|
||||
inline _Tp
|
||||
pair<_T1, _T2>::
|
||||
__do_cons(tuple<_Args...>&& __tuple,
|
||||
const _Index_tuple<_Indexes...>&)
|
||||
{ return _Tp(std::forward<_Args>(get<_Indexes>(__tuple))...); }
|
||||
}
|
||||
|
||||
#endif // __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
|
|
@ -405,6 +405,35 @@ namespace std
|
|||
typedef typename __decay_selector<__remove_type>::__type type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
class reference_wrapper;
|
||||
|
||||
// Helper which adds a reference to a type when given a reference_wrapper
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper
|
||||
{
|
||||
typedef _Tp __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper<reference_wrapper<_Tp> >
|
||||
{
|
||||
typedef _Tp& __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __strip_reference_wrapper<const reference_wrapper<_Tp> >
|
||||
{
|
||||
typedef _Tp& __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __decay_and_strip
|
||||
{
|
||||
typedef typename __strip_reference_wrapper<
|
||||
typename decay<_Tp>::type>::__type __type;
|
||||
};
|
||||
|
||||
|
||||
// Utility for constructing identically cv-qualified types.
|
||||
template<typename _Unqualified, bool _IsConst, bool _IsVol>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// { dg-do compile }
|
||||
// 2009-11-12 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
//
|
||||
// Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2009, 2010 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
|
||||
|
@ -19,7 +19,7 @@
|
|||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 626 }
|
||||
// { dg-error "static assertion failed" "" { target *-*-* } 655 }
|
||||
// { dg-error "instantiated from here" "" { target *-*-* } 30 }
|
||||
// { dg-excess-errors "In function" }
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// 2007-05-03 Benjamin Kosnik <bkoz@redhat.com>
|
||||
//
|
||||
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2007, 2008, 2009, 2010 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
|
||||
|
@ -48,8 +48,8 @@ void test01()
|
|||
// { dg-error "instantiated from here" "" { target *-*-* } 40 }
|
||||
// { dg-error "instantiated from here" "" { target *-*-* } 42 }
|
||||
|
||||
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 588 }
|
||||
// { dg-error "declaration of" "" { target *-*-* } 552 }
|
||||
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 617 }
|
||||
// { dg-error "declaration of" "" { target *-*-* } 581 }
|
||||
|
||||
// { dg-excess-errors "At global scope" }
|
||||
// { dg-excess-errors "In instantiation of" }
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// 2007-05-03 Benjamin Kosnik <bkoz@redhat.com>
|
||||
//
|
||||
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2007, 2008, 2009, 2010 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
|
||||
|
@ -48,8 +48,8 @@ void test01()
|
|||
// { dg-error "instantiated from here" "" { target *-*-* } 40 }
|
||||
// { dg-error "instantiated from here" "" { target *-*-* } 42 }
|
||||
|
||||
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 511 }
|
||||
// { dg-error "declaration of" "" { target *-*-* } 475 }
|
||||
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 540 }
|
||||
// { dg-error "declaration of" "" { target *-*-* } 504 }
|
||||
|
||||
// { dg-excess-errors "At global scope" }
|
||||
// { dg-excess-errors "In instantiation of" }
|
||||
|
|
98
libstdc++-v3/testsuite/20_util/pair/piecewise.cc
Normal file
98
libstdc++-v3/testsuite/20_util/pair/piecewise.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// 2010-04-30 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
//
|
||||
// Copyright (C) 2010 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 3, 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 COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Tuple
|
||||
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
struct type_zero
|
||||
{
|
||||
type_zero() : n_(757) { }
|
||||
|
||||
type_zero(const type_zero&) = delete;
|
||||
type_zero(type_zero&& other) : n_(other.n_) { }
|
||||
|
||||
int get() const { return n_; }
|
||||
|
||||
private:
|
||||
int n_;
|
||||
};
|
||||
|
||||
struct type_one
|
||||
{
|
||||
type_one(int n) : n_(n) { }
|
||||
|
||||
type_one(const type_one&) = delete;
|
||||
type_one(type_one&& other) : n_(other.n_) { }
|
||||
|
||||
int get() const { return n_; }
|
||||
|
||||
private:
|
||||
int n_;
|
||||
};
|
||||
|
||||
struct type_two
|
||||
{
|
||||
type_two(int n1, int n2) : n1_(n1), n2_(n2) { }
|
||||
|
||||
type_two(const type_two&) = delete;
|
||||
type_two(type_two&& other) : n1_(other.n1_), n2_(other.n2_) { }
|
||||
|
||||
int get1() const { return n1_; }
|
||||
int get2() const { return n2_; }
|
||||
|
||||
private:
|
||||
int n1_, n2_;
|
||||
};
|
||||
|
||||
void test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
std::pair<type_one, type_zero> pp0(std::piecewise_construct_t(),
|
||||
std::pack_arguments(-3),
|
||||
std::pack_arguments());
|
||||
VERIFY( pp0.first.get() == -3 );
|
||||
VERIFY( pp0.second.get() == 757 );
|
||||
|
||||
std::pair<type_one, type_two> pp1(std::piecewise_construct_t(),
|
||||
std::pack_arguments(6),
|
||||
std::pack_arguments(5, 4));
|
||||
VERIFY( pp1.first.get() == 6 );
|
||||
VERIFY( pp1.second.get1() == 5 );
|
||||
VERIFY( pp1.second.get2() == 4 );
|
||||
|
||||
std::pair<type_two, type_two> pp2(std::piecewise_construct_t(),
|
||||
std::pack_arguments(2, 1),
|
||||
std::pack_arguments(-1, -3));
|
||||
VERIFY( pp2.first.get1() == 2 );
|
||||
VERIFY( pp2.first.get2() == 1 );
|
||||
VERIFY( pp2.second.get1() == -1 );
|
||||
VERIFY( pp2.second.get2() == -3 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// Copyright (C) 2007, 2009 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2007, 2009, 2010 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
|
||||
|
@ -20,6 +20,7 @@
|
|||
// Tuple
|
||||
|
||||
#include <tuple>
|
||||
#include <utility> // for pair
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using namespace std;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2007, 2008, 2009, 2010 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
|
||||
|
@ -20,6 +20,7 @@
|
|||
// Tuple
|
||||
|
||||
#include <tuple>
|
||||
#include <utility> // for pair
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using namespace std;
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// 2010-04-30 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
//
|
||||
// Copyright (C) 2010 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 3, 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 COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Tuple
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
std::pack_arguments();
|
||||
|
||||
VERIFY( std::get<0>(std::pack_arguments(-1)) == -1 );
|
||||
VERIFY( (std::is_same<decltype(std::pack_arguments(-1)),
|
||||
std::tuple<int&&>>::value) );
|
||||
|
||||
const int i1 = 1;
|
||||
const int i2 = 2;
|
||||
const double d1 = 4.0;
|
||||
auto t1 = std::pack_arguments(i1, i2, d1);
|
||||
VERIFY( (std::is_same<decltype(t1), std::tuple<const int&,
|
||||
const int&, const double&>>::value) );
|
||||
VERIFY( std::get<0>(t1) == i1 );
|
||||
VERIFY( std::get<1>(t1) == i2 );
|
||||
VERIFY( std::get<2>(t1) == d1 );
|
||||
|
||||
typedef const int a_type1[3];
|
||||
a_type1 a1 = { -1, 1, 2 };
|
||||
auto t2 = std::pack_arguments(a1);
|
||||
VERIFY( (std::is_same<decltype(t2), std::tuple<a_type1&>>::value) );
|
||||
VERIFY( std::get<0>(t2)[0] == a1[0] );
|
||||
VERIFY( std::get<0>(t2)[1] == a1[1] );
|
||||
VERIFY( std::get<0>(t2)[2] == a1[2] );
|
||||
|
||||
typedef int a_type2[2];
|
||||
a_type2 a2 = { 2, -2 };
|
||||
volatile int i4 = 1;
|
||||
auto t3 = std::pack_arguments(a2, i4);
|
||||
VERIFY( (std::is_same<decltype(t3), std::tuple<a_type2&,
|
||||
volatile int&>>::value) );
|
||||
VERIFY( std::get<0>(t3)[0] == a2[0] );
|
||||
VERIFY( std::get<0>(t3)[1] == a2[1] );
|
||||
VERIFY( std::get<1>(t3) == i4 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue