| // Test for Container using non-standard pointer types. | |
| // Copyright (C) 2008-2026 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; | |
| } |