// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // utility.h -- // // Author : Richard C. Bilson // Created On : Mon May 18 07:44:20 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Fri Jul 21 22:19:13 2017 // Update Count : 33 // #pragma once #include #include #include #include #include #include #include #include #include template< typename T > static inline T * maybeClone( const T *orig ) { if ( orig ) { return orig->clone(); } else { return 0; } // if } template< typename T, typename U > struct maybeBuild_t { static T * doit( const U *orig ) { if ( orig ) { return orig->build(); } else { return 0; } // if } }; template< typename T, typename U > static inline T * maybeBuild( const U *orig ) { return maybeBuild_t::doit(orig); } template< typename T, typename U > static inline T * maybeMoveBuild( const U *orig ) { T* ret = maybeBuild(orig); delete orig; return ret; } template< typename Input_iterator > void printEnums( Input_iterator begin, Input_iterator end, const char * const *name_array, std::ostream &os ) { for ( Input_iterator i = begin; i != end; ++i ) { os << name_array[ *i ] << ' '; } // for } template< typename Container > void deleteAll( Container &container ) { for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) { delete *i; } // for } template< typename Container > void printAll( const Container &container, std::ostream &os, int indent = 0 ) { for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) { if ( *i ) { os << std::string( indent, ' ' ); (*i)->print( os, indent + 2 ); // need an endl after each element because it's not easy to know when each individual item should end os << std::endl; } // if } // for } template< typename SrcContainer, typename DestContainer > void cloneAll( const SrcContainer &src, DestContainer &dest ) { typename SrcContainer::const_iterator in = src.begin(); std::back_insert_iterator< DestContainer > out( dest ); while ( in != src.end() ) { *out++ = (*in++)->clone(); } // while } template< typename Container > void assertAll( const Container &container ) { int count = 0; for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) { if ( !(*i) ) { std::cerr << count << " is null" << std::endl; } // if } // for } template < typename T > std::list tail( std::list l ) { if ( ! l.empty() ) { std::list ret(++(l.begin()), l.end()); return ret; } // if } template < typename T > std::list flatten( std::list < std::list > l) { typedef std::list Ts; Ts ret; switch ( l.size() ) { case 0: return ret; case 1: return l.front(); default: ret = flatten(tail(l)); ret.insert(ret.begin(), l.front().begin(), l.front().end()); return ret; } // switch } template < typename T > void toString_single( std::ostream & os, const T & value ) { os << value; } template < typename T, typename... Params > void toString_single( std::ostream & os, const T & value, const Params & ... params ) { os << value; toString_single( os, params ... ); } template < typename ... Params > std::string toString( const Params & ... params ) { std::ostringstream os; toString_single( os, params... ); return os.str(); } // replace element of list with all elements of another list template< typename T > void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) { typename std::list< T >::iterator next = pos; advance( next, 1 ); //if ( next != org.end() ) { org.erase( pos ); org.splice( next, with ); //} return; } // replace range of a list with a single element template< typename T > void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) { org.insert( begin, with ); org.erase( begin, end ); } template< typename... Args > auto filter(Args&&... args) -> decltype(std::copy_if(std::forward(args)...)) { return std::copy_if(std::forward(args)...); } template< typename... Args > auto zip(Args&&... args) -> decltype(zipWith(std::forward(args)..., std::make_pair)) { return zipWith(std::forward(args)..., std::make_pair); } template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction > void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) { while ( b1 != e1 && b2 != e2 ) *out++ = func(*b1++, *b2++); } // it's nice to actually be able to increment iterators by an arbitrary amount template< class InputIt, class Distance > InputIt operator+( InputIt it, Distance n ) { advance(it, n); return it; } template< typename T > void warn_single( const T & arg ) { std::cerr << arg << std::endl; } template< typename T, typename... Params > void warn_single(const T & arg, const Params & ... params ) { std::cerr << arg; warn_single( params... ); } template< typename... Params > void warn( const Params & ... params ) { std::cerr << "Warning: "; warn_single( params... ); } // ----------------------------------------------------------------------------- // Ref Counted Singleton class // Objects that inherit from this class will have at most one reference to it // but if all references die, the object will be deleted. template< typename ThisType > class RefCountSingleton { public: static std::shared_ptr get() { if( global_instance.expired() ) { std::shared_ptr new_instance = std::make_shared(); global_instance = new_instance; return std::move(new_instance); } return global_instance.lock(); } private: static std::weak_ptr global_instance; }; template< typename ThisType > std::weak_ptr RefCountSingleton::global_instance; // ----------------------------------------------------------------------------- // RAII object to regulate "save and restore" behaviour, e.g. // void Foo::bar() { // ValueGuard guard(var); // var is a member of type Foo // var = ...; // } // var's original value is restored template< typename T > struct ValueGuard { T old; T& ref; ValueGuard(T& inRef) : old(inRef), ref(inRef) {} ~ValueGuard() { ref = old; } }; template< typename T > struct ValueGuardPtr { T old; T* ref; ValueGuardPtr(T * inRef) : old( inRef ? *inRef : T() ), ref(inRef) {} ~ValueGuardPtr() { if( ref ) *ref = old; } }; template< typename T > struct ValueGuardPtr< std::list< T > > { std::list< T > old; std::list< T >* ref; ValueGuardPtr( std::list< T > * inRef) : old(), ref(inRef) { if( ref ) { swap( *ref, old ); } } ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } }; // ----------------------------------------------------------------------------- // Helper struct and function to support // for ( val : reverseIterate( container ) ) {} // syntax to have a for each that iterates backwards template< typename T > struct reverse_iterate_t { T& ref; reverse_iterate_t( T & ref ) : ref(ref) {} typedef typename T::reverse_iterator iterator; iterator begin() { return ref.rbegin(); } iterator end() { return ref.rend(); } }; template< typename T > reverse_iterate_t< T > reverseIterate( T & ref ) { return reverse_iterate_t< T >( ref ); } template< typename OutType, typename Range, typename Functor > OutType map_range( const Range& range, Functor&& functor ) { OutType out; std::transform( begin( range ), end( range ), std::back_inserter( out ), std::forward< Functor >( functor ) ); return out; } // ----------------------------------------------------------------------------- // Helper struct and function to support // for ( val : group_iterate( container1, container2, ... ) ) {} // syntax to have a for each that iterates multiple containers of the same length // TODO: update to use variadic arguments, perfect forwarding template< typename T1, typename T2 > struct group_iterate_t { group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) { assertf(v1.size() == v2.size(), "group iteration requires containers of the same size."); }; struct iterator { typedef std::tuple value_type; typedef typename T1::iterator T1Iter; typedef typename T2::iterator T2Iter; typedef std::tuple IterTuple; IterTuple it; iterator( T1Iter i1, T2Iter i2 ) : it( i1, i2 ) {} iterator operator++() { return iterator( ++std::get<0>(it), ++std::get<1>(it) ); } bool operator!=( const iterator &other ) const { return it != other.it; } value_type operator*() const { return std::make_tuple( *std::get<0>(it), *std::get<1>(it) ); } }; iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); } iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); } private: std::tuple args; }; template< typename... Args > group_iterate_t group_iterate( const Args &... args ) { return group_iterate_t(args...); } struct CodeLocation { int linenumber; std::string filename; /// Create a new unset CodeLocation. CodeLocation() : linenumber( -1 ) , filename("") {} /// Create a new CodeLocation with the given values. CodeLocation( const char* filename, int lineno ) : linenumber( lineno ) , filename(filename ? filename : "") {} CodeLocation( const CodeLocation& rhs ) = default; bool isSet () const { return -1 != linenumber; } bool isUnset () const { return !isSet(); } void unset () { linenumber = -1; filename = ""; } // Use field access for set. }; inline std::string to_string( const CodeLocation& location ) { return location.isSet() ? location.filename + ":" + std::to_string(location.linenumber) + " " : ""; } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //