Changeset b110bcc for src/Common/utility.h
- Timestamp:
- Apr 21, 2023, 5:36:12 PM (2 years ago)
- Branches:
- ADT, master
- Children:
- 28f8f15, 6e4c44d
- Parents:
- 2ed94a9 (diff), 699a97d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/utility.h
r2ed94a9 rb110bcc 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h -- 7 // utility.h -- General utilities used across the compiler. 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 25 14:26:00 202213 // Update Count : 5 112 // Last Modified On : Fri Feb 17 15:25:00 2023 13 // Update Count : 53 14 14 // 15 15 … … 19 19 #include <cctype> 20 20 #include <algorithm> 21 #include <functional>22 21 #include <iostream> 23 #include <iterator>24 22 #include <list> 25 23 #include <memory> 26 #include <sstream>27 24 #include <string> 28 25 #include <type_traits> 29 #include <utility>30 26 #include <vector> 31 27 #include <cstring> // memcmp … … 49 45 return 0; 50 46 } // if 51 }52 53 template< typename T, typename U >54 struct maybeBuild_t {55 static T * doit( const U *orig ) {56 if ( orig ) {57 return orig->build();58 } else {59 return 0;60 } // if61 }62 };63 64 template< typename T, typename U >65 static inline T * maybeBuild( const U *orig ) {66 return maybeBuild_t<T,U>::doit(orig);67 }68 69 template< typename T, typename U >70 static inline T * maybeMoveBuild( const U *orig ) {71 T* ret = maybeBuild<T>(orig);72 delete orig;73 return ret;74 47 } 75 48 … … 168 141 splice( src, dst ); 169 142 dst.swap( src ); 170 }171 172 template < typename T >173 void toString_single( std::ostream & os, const T & value ) {174 os << value;175 }176 177 template < typename T, typename... Params >178 void toString_single( std::ostream & os, const T & value, const Params & ... params ) {179 os << value;180 toString_single( os, params ... );181 }182 183 template < typename ... Params >184 std::string toString( const Params & ... params ) {185 std::ostringstream os;186 toString_single( os, params... );187 return os.str();188 }189 190 #define toCString( ... ) toString( __VA_ARGS__ ).c_str()191 192 // replace element of list with all elements of another list193 template< typename T >194 void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {195 typename std::list< T >::iterator next = pos; advance( next, 1 );196 197 //if ( next != org.end() ) {198 org.erase( pos );199 org.splice( next, with );200 //}201 202 return;203 }204 205 // replace range of a list with a single element206 template< typename T >207 void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {208 org.insert( begin, with );209 org.erase( begin, end );210 143 } 211 144 … … 236 169 } 237 170 238 template< typename... Args >239 auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {240 return zipWith(std::forward<Args>(args)..., std::make_pair);241 }242 243 template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >244 void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {245 while ( b1 != e1 && b2 != e2 )246 *out++ = func(*b1++, *b2++);247 }248 249 // it's nice to actually be able to increment iterators by an arbitrary amount250 template< class InputIt, class Distance >251 InputIt operator+( InputIt it, Distance n ) {252 advance(it, n);253 return it;254 }255 256 template< typename T >257 void warn_single( const T & arg ) {258 std::cerr << arg << std::endl;259 }260 261 template< typename T, typename... Params >262 void warn_single(const T & arg, const Params & ... params ) {263 std::cerr << arg;264 warn_single( params... );265 }266 267 template< typename... Params >268 void warn( const Params & ... params ) {269 std::cerr << "Warning: ";270 warn_single( params... );271 }272 273 171 // determines if pref is a prefix of str 274 172 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 275 173 if ( pref.size() > str.size() ) return false; 276 return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() ); 277 // return prefix == full.substr(0, prefix.size()); // for future, requires c++17 278 } 279 280 // ----------------------------------------------------------------------------- 281 // Ref Counted Singleton class 282 // Objects that inherit from this class will have at most one reference to it 283 // but if all references die, the object will be deleted. 284 285 template< typename ThisType > 286 class RefCountSingleton { 287 public: 288 static std::shared_ptr<ThisType> get() { 289 if( global_instance.expired() ) { 290 std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>(); 291 global_instance = new_instance; 292 return std::move(new_instance); 293 } 294 return global_instance.lock(); 295 } 296 private: 297 static std::weak_ptr<ThisType> global_instance; 298 }; 299 300 template< typename ThisType > 301 std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance; 174 return pref == str.substr(start, pref.size()); 175 } 302 176 303 177 // ----------------------------------------------------------------------------- … … 356 230 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 357 231 }; 358 359 // -----------------------------------------------------------------------------360 // Helper struct and function to support361 // for ( val : reverseIterate( container ) ) {}362 // syntax to have a for each that iterates backwards363 364 template< typename T >365 struct reverse_iterate_t {366 T& ref;367 368 reverse_iterate_t( T & ref ) : ref(ref) {}369 370 // this does NOT work on const T!!!371 // typedef typename T::reverse_iterator iterator;372 auto begin() { return ref.rbegin(); }373 auto end() { return ref.rend(); }374 };375 376 template< typename T >377 reverse_iterate_t< T > reverseIterate( T & ref ) {378 return reverse_iterate_t< T >( ref );379 }380 381 template< typename T >382 struct enumerate_t {383 template<typename val_t>384 struct value_t {385 val_t & val;386 size_t idx;387 };388 389 template< typename iter_t, typename val_t >390 struct iterator_t {391 iter_t it;392 size_t idx;393 394 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}395 396 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }397 398 bool operator==(const iterator_t & o) const { return o.it == it; }399 bool operator!=(const iterator_t & o) const { return o.it != it; }400 401 iterator_t & operator++() {402 it++;403 idx++;404 return *this;405 }406 407 using difference_type = typename std::iterator_traits< iter_t >::difference_type;408 using value_type = value_t<val_t>;409 using pointer = value_t<val_t> *;410 using reference = value_t<val_t> &;411 using iterator_category = std::forward_iterator_tag;412 };413 414 T & ref;415 416 using iterator = iterator_t< typename T::iterator, typename T::value_type >;417 using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;418 419 iterator begin() { return iterator( ref.begin(), 0 ); }420 iterator end() { return iterator( ref.end(), ref.size() ); }421 422 const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }423 const_iterator end() const { return const_iterator( ref.cend(), ref.size() ); }424 425 const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }426 const_iterator cend() const { return const_iterator( ref.cend(), ref.size() ); }427 };428 429 template< typename T >430 enumerate_t<T> enumerate( T & ref ) {431 return enumerate_t< T >{ ref };432 }433 434 template< typename T >435 const enumerate_t< const T > enumerate( const T & ref ) {436 return enumerate_t< const T >{ ref };437 }438 439 template< typename OutType, typename Range, typename Functor >440 OutType map_range( const Range& range, Functor&& functor ) {441 OutType out;442 443 std::transform(444 begin( range ),445 end( range ),446 std::back_inserter( out ),447 std::forward< Functor >( functor )448 );449 450 return out;451 }452 453 // -----------------------------------------------------------------------------454 // Helper struct and function to support:455 // for ( auto val : group_iterate( container1, container2, ... ) ) { ... }456 // This iteraters through multiple containers of the same size.457 458 template<typename... Args>459 class group_iterate_t {460 using Iterables = std::tuple<Args...>;461 Iterables iterables;462 463 // Getting the iterator and value types this way preserves const.464 template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());465 template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());466 template<typename> struct base_iterator;467 468 // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`469 // into a pack. These are the indexes into the tuples, so unpacking can470 // go over each element of the tuple.471 // The std::integer_sequence is just used to build that sequence.472 // A library reference will probably explain it better than I can.473 template<std::size_t... Indices>474 struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {475 using value_type = std::tuple< Data<Indices>... >;476 std::tuple<Iter<Indices>...> iterators;477 478 base_iterator( Iter<Indices>... is ) : iterators( is... ) {}479 base_iterator operator++() {480 return base_iterator( ++std::get<Indices>( iterators )... );481 }482 bool operator!=( const base_iterator& other ) const {483 return iterators != other.iterators;484 }485 value_type operator*() const {486 return std::tie( *std::get<Indices>( iterators )... );487 }488 489 static base_iterator make_begin( Iterables & data ) {490 return base_iterator( std::get<Indices>( data ).begin()... );491 }492 static base_iterator make_end( Iterables & data ) {493 return base_iterator( std::get<Indices>( data ).end()... );494 }495 };496 497 public:498 group_iterate_t( const Args &... args ) : iterables( args... ) {}499 500 using iterator = base_iterator<decltype(501 std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;502 503 iterator begin() { return iterator::make_begin( iterables ); }504 iterator end() { return iterator::make_end( iterables ); }505 };506 507 // Helpers for the bounds checks (the non-varatic part of group_iterate):508 static inline void runGroupBoundsCheck(size_t size0, size_t size1) {509 assertf( size0 == size1,510 "group iteration requires containers of the same size: <%zd, %zd>.",511 size0, size1 );512 }513 514 static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {515 assertf( size0 == size1 && size1 == size2,516 "group iteration requires containers of the same size: <%zd, %zd, %zd>.",517 size0, size1, size2 );518 }519 520 /// Performs bounds check to ensure that all arguments are of the same length.521 template< typename... Args >522 group_iterate_t<Args...> group_iterate( Args &&... args ) {523 runGroupBoundsCheck( args.size()... );524 return group_iterate_t<Args...>( std::forward<Args>( args )... );525 }526 527 /// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.528 template< typename... Args >529 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {530 return group_iterate_t<Args...>( std::forward<Args>( args )... );531 }532 533 // -----------------------------------------------------------------------------534 // Helper struct and function to support535 // for ( val : lazy_map( container1, f ) ) {}536 // syntax to have a for each that iterates a container, mapping each element by applying f537 template< typename T, typename Func >538 struct lambda_iterate_t {539 const T & ref;540 std::function<Func> f;541 542 struct iterator {543 typedef decltype(begin(ref)) Iter;544 Iter it;545 std::function<Func> f;546 iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}547 iterator & operator++() {548 ++it; return *this;549 }550 bool operator!=( const iterator &other ) const { return it != other.it; }551 auto operator*() const -> decltype(f(*it)) { return f(*it); }552 };553 554 lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}555 556 auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }557 auto end() const -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }558 };559 560 template< typename... Args >561 lambda_iterate_t<Args...> lazy_map( const Args &... args ) {562 return lambda_iterate_t<Args...>( args...);563 }564 232 565 233 // ----------------------------------------------------------------------------- … … 583 251 } // ilog2 584 252 585 // -----------------------------------------------------------------------------586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated587 std::pair<long long int, bool> eval(const Expression * expr);588 589 namespace ast {590 class Expr;591 }592 593 std::pair<long long int, bool> eval(const ast::Expr * expr);594 595 // -----------------------------------------------------------------------------596 /// Reorders the input range in-place so that the minimal-value elements according to the597 /// comparator are in front;598 /// returns the iterator after the last minimal-value element.599 template<typename Iter, typename Compare>600 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {601 if ( begin == end ) return end;602 603 Iter min_pos = begin;604 for ( Iter i = begin + 1; i != end; ++i ) {605 if ( lt( *i, *min_pos ) ) {606 // new minimum cost; swap into first position607 min_pos = begin;608 std::iter_swap( min_pos, i );609 } else if ( ! lt( *min_pos, *i ) ) {610 // duplicate minimum cost; swap into next minimum position611 ++min_pos;612 std::iter_swap( min_pos, i );613 }614 }615 return ++min_pos;616 }617 618 template<typename Iter, typename Compare>619 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {620 return sort_mins( begin, end, lt );621 }622 623 /// sort_mins defaulted to use std::less624 template<typename Iter>625 inline Iter sort_mins( Iter begin, Iter end ) {626 return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );627 }628 629 253 // Local Variables: // 630 254 // tab-width: 4 //
Note:
See TracChangeset
for help on using the changeset viewer.