1+ // ==========================================================================
2+ // Implementation: added new pointer class
3+ // this is an example of smart_pointer_type_trait.hpp's additional type trait guide.
4+ // ==========================================================================
5+
6+ #include < iostream>
7+ #include " smart_pointer_type_trait.hpp"
8+
9+ template < typename Ty >
10+ class value_pointer
11+ {
12+ public:
13+ // methods
14+ void reset ( const Ty& val = Ty{} )
15+ {
16+ if ( !raw_ptr ) raw_ptr = new Ty{ val };
17+ else *raw_ptr = val;
18+ }
19+
20+ void reset ( Ty&& val )
21+ {
22+ if ( !raw_ptr ) raw_ptr = new Ty{ std::move ( val ) };
23+ else *raw_ptr = std::move_if_noexcept ( val );
24+ }
25+
26+ void release ()
27+ {
28+ delete raw_ptr;
29+ raw_ptr = nullptr ;
30+ }
31+
32+ void swap ( value_pointer& right )
33+ {
34+ if ( !raw_ptr ) throw std::exception{ " value_pointer< Ty >::swap(): raw_ptr was null pointer." };
35+ if ( !right.raw_ptr ) throw std::exception{ " value_pointer< Ty >::swap(): invalid argument( right was null pointer. )" };
36+
37+ auto temp = std::move_if_noexcept ( *right.raw_ptr );
38+ *right.raw_ptr = std::move_if_noexcept ( *raw_ptr );
39+ *raw_ptr = std::move_if_noexcept ( temp );
40+ }
41+
42+ // operators
43+ Ty& operator *() { return *raw_ptr; }
44+ const Ty& operator *() const { return *raw_ptr; }
45+ Ty* operator ->() { return raw_ptr; }
46+ const Ty* operator ->() const { return raw_ptr; }
47+
48+ // special member functions
49+ value_pointer ( const Ty& val ) : raw_ptr{ new Ty{ val } } {}
50+ value_pointer ( Ty&& val ) : raw_ptr{ new Ty{ std::move ( val ) } } {}
51+ value_pointer ( const value_pointer& other ) : raw_ptr{ new Ty{ *other } } {}
52+ value_pointer& operator =( const value_pointer& other )
53+ {
54+ if ( this != &other ) reset ( *other );
55+ return *this ;
56+ }
57+ value_pointer ( value_pointer&& other ) noexcept : raw_ptr{ new Ty{ std::move ( *other ) } } {}
58+ value_pointer& operator =( value_pointer&& other ) noexcept
59+ {
60+ if ( this != &other ) reset ( std::move ( *other ) );
61+ return *this ;
62+ }
63+ ~value_pointer () { if ( raw_ptr ) delete raw_ptr; }
64+
65+ private:
66+ Ty* raw_ptr;
67+ };
68+
69+ template < typename Ty >
70+ struct Vptr : value_pointer< Ty > {};
71+
72+ // =====================================================================
73+ // *********************************************************************
74+ // new type trait ( value_ptr )
75+ // just retyped the pointer's name.
76+ // *********************************************************************
77+ // =====================================================================
78+
79+ namespace woon2
80+ {
81+ namespace detail
82+ {
83+ template < typename T >
84+ struct is_value_pointer_impl : std::false_type {};
85+
86+ template < typename T >
87+ struct is_value_pointer_impl < value_pointer< T > > : std::true_type {};
88+
89+ template < typename T >
90+ std::true_type is_value_pointer_soft_impl ( value_pointer< T >* );
91+ std::false_type is_value_pointer_soft_impl ( ... );
92+ }
93+
94+ template < typename T >
95+ using is_value_pointer = detail::is_value_pointer_impl< detail::remove_cvr_t < T > >;
96+
97+ template < typename T >
98+ constexpr bool is_value_pointer_v = is_value_pointer< T >::value;
99+
100+ template < typename T >
101+ using is_value_pointer_soft = decltype ( detail::is_value_pointer_soft_impl( std::declval< detail::remove_cvr_t < T >* >() ) );
102+
103+ template < typename T >
104+ constexpr bool is_value_pointer_soft_v = is_value_pointer_soft< T >::value;
105+ }
106+
107+ // =====================================================================
108+
109+ struct INT
110+ {
111+ INT ( int impl = 0 ) : impl{ impl } { std::cout << " INT constructor called\n " ; }
112+ ~INT () { std::cout << " INT destructor called\n " ; }
113+ INT ( const INT& other ) : impl{ other.impl } { std::cout << " INT copy constructor called\n " ; }
114+ INT& operator =( const INT& other )
115+ {
116+ if ( this != &other )
117+ {
118+ std::cout << " INT copy allocator called\n " ;
119+ impl = other.impl ;
120+ }
121+
122+ return *this ;
123+ }
124+ INT ( INT&& other ) noexcept : impl{ other.impl } { std::cout << " INT move constructor called\n " ; }
125+ INT& operator =( INT&& other ) noexcept
126+ {
127+ if ( this != &other )
128+ {
129+ std::cout << " INT move allocator called\n " ;
130+ impl = other.impl ;
131+ }
132+
133+ return *this ;
134+ }
135+ operator int () { return impl; }
136+
137+ int impl;
138+ };
139+
140+ int main ()
141+ {
142+ // test type traits ==============================================
143+ static_assert ( woon2::is_pointable_v< value_pointer< int > >, " is_pointable trait doesn't work." );
144+ static_assert ( woon2::is_value_pointer_v< value_pointer< int > >, " is_value_pointer trait doesn't work." );
145+ static_assert ( woon2::is_value_pointer_soft_v< Vptr< int > >, " is_value_pointer_soft trait doesn't work." );
146+ static_assert ( !woon2::has_get_deleter_v< value_pointer< int > >, " has_get_deleter trait doesn't work." );
147+ static_assert ( woon2::has_release_v< value_pointer< int > >, " has_release trait doesn't work." );
148+ static_assert ( woon2::has_swap_v< value_pointer< int > >, " has_swap trait doesn't work." );
149+ static_assert ( woon2::has_reset_v< value_pointer< int > >, " has_reset trait doesn't work." );
150+ // ===============================================================
151+
152+ std::cout << " ====================================================\n " ;
153+ std::cout << " value_pointer test\n " ;
154+ std::cout << " ====================================================\n\n\n " ;
155+
156+ try {
157+ std::cout << " construct a ========================================\n " ;
158+ value_pointer< INT > a{ 3 };
159+ std::cout << " ====================================================\n\n\n " ;
160+
161+ std::cout << " construct b ========================================\n " ;
162+ value_pointer< INT > b{ 4 };
163+ std::cout << " ====================================================\n\n\n " ;
164+
165+ std::cout << " print values =======================================\n " ;
166+ std::cout << " a: " << *a << " , b: " << *b << ' \n ' ;
167+ std::cout << " ====================================================\n\n\n " ;
168+
169+ std::cout << " swap a, b ==========================================\n " ;
170+ a.swap ( b );
171+ std::cout << " ====================================================\n\n\n " ;
172+
173+ std::cout << " print values =======================================\n " ;
174+ std::cout << " a: " << *a << " , b: " << *b << ' \n ' ;
175+ std::cout << " ====================================================\n\n\n " ;
176+
177+ std::cout << " release a ==========================================\n " ;
178+ a.release ();
179+ std::cout << " ====================================================\n\n\n " ;
180+
181+ std::cout << " reset a with b =====================================\n " ;
182+ a.reset ( *b );
183+ std::cout << " ====================================================\n\n\n " ;
184+
185+ std::cout << " print values =======================================\n " ;
186+ std::cout << " a: " << *a << " , b: " << *b << ' \n ' ;
187+ std::cout << " ====================================================\n\n\n " ;
188+
189+ std::cout << " must call destructors ==============================\n " ;
190+ }
191+ catch ( const std::exception& e )
192+ {
193+ std::cout << e.what ();
194+ exit ( -1 );
195+ }
196+ }
0 commit comments