| // Test for Container using non-standard pointer types. |
| |
| // Copyright (C) 2008-2021 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/>. |
| |
| |
| #include <algorithm> |
| #include <testsuite_hooks.h> |
| #include <ext/cast.h> |
| #include <ext/pointer.h> |
| |
| using __gnu_cxx::_Pointer_adapter; |
| using __gnu_cxx::_Relative_pointer_impl; |
| using __gnu_cxx::__static_pointer_cast; |
| using __gnu_cxx::__const_pointer_cast; |
| |
| |
| void |
| test01() { |
| typedef _Pointer_adapter<_Relative_pointer_impl<int> > pointer; |
| typedef _Pointer_adapter<_Relative_pointer_impl<const int> > const_pointer; |
| |
| int A[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
| |
| // basic pointer assignment/access tests. |
| pointer x = &A[0]; |
| VERIFY(*x == 0); |
| VERIFY(std::equal(x, x+10, A)); |
| pointer y(&A[9]); |
| VERIFY(*y == 9); |
| |
| // assignability |
| pointer z(x); |
| VERIFY(z==x); |
| VERIFY(*z == 0); |
| |
| z = y; |
| VERIFY(z==y); |
| VERIFY(z!=x); |
| VERIFY(z>x); |
| VERIFY(*z == 9); |
| |
| // pointer arithmetic |
| VERIFY(*++x == 1); |
| VERIFY(*--x == 0); |
| VERIFY(*(x++) == 0); |
| VERIFY(*(x--) == 1); |
| VERIFY(*(x+2) == 2); |
| VERIFY(*(2+x) == 2); |
| VERIFY(*(y-2) == 7); |
| VERIFY(y - x == 9); |
| VERIFY(&*y - x == 9); |
| VERIFY(y - &*x == 9); |
| |
| size_t s(y - x); |
| VERIFY(s == 9); |
| } |
| |
| |
| struct A { |
| mutable int i; |
| }; |
| struct B : public A{ |
| mutable int j; |
| }; |
| typedef _Pointer_adapter<_Relative_pointer_impl<B> > B_pointer; |
| typedef _Pointer_adapter<_Relative_pointer_impl<A> > A_pointer; |
| typedef _Pointer_adapter<_Relative_pointer_impl<const A> > const_A_pointer; |
| typedef _Pointer_adapter<_Relative_pointer_impl<const B> > const_B_pointer; |
| |
| |
| // Test implicit conversion from B* to A* |
| void inc(_Pointer_adapter<_Relative_pointer_impl<A> > a) { |
| a->i++; |
| } |
| // Test implicit conversion from B* to const B* |
| void inc2(_Pointer_adapter<_Relative_pointer_impl<const B> > b) { |
| b->i++; |
| b->j++; |
| } |
| // Test implicit conversion from B* to const A* |
| void inc3(_Pointer_adapter<_Relative_pointer_impl<const A> > a) { |
| a->i++; |
| } |
| |
| void test02() { |
| B b; |
| b.i = 2; |
| b.j = 2; |
| |
| B_pointer Bptr(&b); |
| VERIFY(Bptr->i == 2); |
| Bptr->i++; |
| VERIFY(b.i == 3); |
| |
| const_B_pointer cBptr(&b); |
| b.i++; |
| VERIFY(cBptr->i == 4); |
| |
| A_pointer Aptr(&b); |
| b.i++; |
| VERIFY(Aptr->i == 5); |
| Aptr->i++; |
| VERIFY(b.i == 6); |
| |
| const_A_pointer cAptr(&b); |
| b.i++; |
| VERIFY(cAptr->i == 7); |
| |
| const_B_pointer cBptr2(Bptr); |
| b.i++; |
| VERIFY(cBptr2->i == 8); |
| |
| A_pointer Aptr2(Bptr); |
| b.i++; |
| VERIFY(Aptr2->i == 9); |
| Aptr2->i++; |
| VERIFY(b.i == 10); |
| |
| const_A_pointer cAptr2(Bptr); |
| b.i++; |
| VERIFY(cAptr2->i == 11); |
| |
| // Implicit casting during invocation |
| inc(Bptr); |
| VERIFY(Bptr->i == 12); |
| inc2(Bptr); |
| VERIFY(Bptr->i == 13); |
| VERIFY(Bptr->j == 3); |
| inc3(Bptr); |
| VERIFY(Bptr->i == 14); |
| } |
| |
| void test03() { |
| B b; |
| B* bPtr = &b; |
| A* aPtr __attribute__((unused)) = __static_pointer_cast<A*>(bPtr); |
| const A *caPtr __attribute__((unused)) = __static_pointer_cast<const A*>(bPtr); |
| const B *cbPtr __attribute__((unused)) = __static_pointer_cast<const B*>(bPtr); |
| |
| B_pointer Bptr2 = &b; |
| |
| const A* caPtr2 __attribute__((unused)) = __static_pointer_cast<const A*>(Bptr2); |
| A * aPtr2 __attribute__((unused)) = __static_pointer_cast<A*>(Bptr2); |
| const B* cbPtr2 __attribute__((unused)) = __const_pointer_cast<const B*>(Bptr2); |
| |
| const_A_pointer caPtr3 __attribute__((unused)) = __static_pointer_cast<const A*>(Bptr2); |
| A_pointer aPtr3 __attribute__((unused)) = __static_pointer_cast<A*>(Bptr2); |
| const_B_pointer cbPtr3 __attribute__((unused)) = __const_pointer_cast<const B*>(Bptr2); |
| } |
| |
| // Confirm the usability of the __static_pointer_cast<> template function |
| // to transform between _Pointer_adapter and standard versions. |
| void test04() { |
| B b; |
| B_pointer bPtr = &b; |
| |
| A_pointer aPtr = __static_pointer_cast<A_pointer>(bPtr); |
| VERIFY(aPtr == bPtr); |
| B_pointer bPtr2 = __static_pointer_cast<B_pointer>(aPtr); |
| VERIFY(bPtr2 == aPtr); |
| |
| A* aPtr3 = __static_pointer_cast<A*>(bPtr); |
| VERIFY(aPtr3 == bPtr); |
| B* bPtr3 = __static_pointer_cast<B*>(aPtr); |
| VERIFY(bPtr3 == aPtr); |
| } |
| |
| // Check that long long values can be used for pointer arithmetic. |
| void test05() |
| { |
| A a[2] = { 1, 2 }; |
| A_pointer p = a; |
| A_pointer q = p + 0ull; |
| VERIFY( p == q ); |
| q += 0ll; |
| VERIFY( p == q ); |
| q += 1ll; |
| VERIFY( q->i == p[1ll].i ); |
| } |
| |
| int main() |
| { |
| test01(); |
| test02(); |
| test03(); |
| test04(); |
| test05(); |
| return 0; |
| } |