diff --git a/include/daw/daw_iterator_traits.h b/include/daw/daw_iterator_traits.h index ca702a5d2..69db8e231 100644 --- a/include/daw/daw_iterator_traits.h +++ b/include/daw/daw_iterator_traits.h @@ -19,12 +19,13 @@ namespace daw { template - using iter_value_t = - typename std::iterator_traits>::value_type; + using iter_reference_t = decltype( *std::declval( ) ); template - using iter_reference_t = - typename std::iterator_traits>::reference; + using iter_const_reference_t = decltype( *std::declval( ) ); + + template + using iter_value_t = std::remove_cvref_t>; template using iter_pointer_t = @@ -34,17 +35,13 @@ namespace daw { using iter_difference_t = typename std::iterator_traits>::difference_type; - template - using iter_const_reference_t = - std::common_reference_t const &&, iter_reference_t>; - template using iter_category_t = typename std::iterator_traits>::iterator_category; template concept Iterator = requires( It & it ) { - { ++it } -> std::same_as; + { ++it }->std::same_as; { it++ }; { *it }; }; @@ -170,18 +167,24 @@ namespace daw { }; template - using iterator_t = DAW_TYPEOF( std::begin( std::declval( ) ) ); + using iterator_t = DAW_TYPEOF( std::begin( std::declval( ) ) ); + + template + using iterator_cbegin_t = DAW_TYPEOF( std::cbegin( std::declval( ) ) ); + + template + using iterator_end_t = DAW_TYPEOF( std::end( std::declval( ) ) ); template - using iterator_end_t = DAW_TYPEOF( std::end( std::declval( ) ) ); + using iterator_cend_t = DAW_TYPEOF( std::cend( std::declval( ) ) ); template using const_iterator_t = - DAW_TYPEOF( std::cbegin( std::declval( ) ) ); + DAW_TYPEOF( std::cbegin( std::declval( ) ) ); template using const_iterator_end_t = - DAW_TYPEOF( std::cend( std::declval( ) ) ); + DAW_TYPEOF( std::cend( std::declval( ) ) ); template using range_value_t = iter_value_t>; diff --git a/include/daw/pipelines/chunk.h b/include/daw/pipelines/chunk.h index d27a68ebe..246b438e0 100644 --- a/include/daw/pipelines/chunk.h +++ b/include/daw/pipelines/chunk.h @@ -8,6 +8,7 @@ #pragma once +#include "daw/cpp_17.h" #include "daw/daw_attributes.h" #include "daw/daw_iterator_traits.h" #include "daw/daw_move.h" @@ -54,7 +55,9 @@ namespace daw::pipelines::pimpl { public: explicit chunk_view( ) = default; - explicit chunk_view( Range auto &&r ) + template + requires( not std::same_as, chunk_view> ) // + explicit chunk_view( U &&r ) : m_range{ DAW_FWD( r ) } , m_iter{ std::begin( m_range ) } {} @@ -119,9 +122,9 @@ namespace daw::pipelines::pimpl { operator!=( chunk_view const &rhs ) const noexcept = default; }; template - chunk_view( R &&r ) -> chunk_view; + chunk_view( R &&r ) -> chunk_view>; template - chunk_view( R &&r, std::size_t ) -> chunk_view; + chunk_view( R &&r, std::size_t ) -> chunk_view>; struct Chunk_t { std::size_t chunk_size; diff --git a/include/daw/pipelines/concat.h b/include/daw/pipelines/concat.h index 448761310..7766b0b61 100644 --- a/include/daw/pipelines/concat.h +++ b/include/daw/pipelines/concat.h @@ -115,7 +115,8 @@ namespace daw::pipelines { } }; template - concat_view( Ranges &&... ) -> concat_view; + concat_view( Ranges &&... ) + -> concat_view...>; namespace pimpl { struct Concat_t { diff --git a/include/daw/pipelines/flatten.h b/include/daw/pipelines/flatten.h index d17d9f568..ae42c1d12 100644 --- a/include/daw/pipelines/flatten.h +++ b/include/daw/pipelines/flatten.h @@ -38,7 +38,7 @@ namespace daw::pipelines::pimpl { template struct flatten_view : range_base_t, flatten_view_end_t> { using iterator_t = daw::iterator_t; - using sub_iterator_t = daw::iterator_t>; + using sub_iterator_t = daw::iterator_t>; using iterator_category = std::forward_iterator_tag; using value_type = daw::iter_value_t; using reference = daw::iter_reference_t; @@ -50,23 +50,15 @@ namespace daw::pipelines::pimpl { using end_t = flatten_view_end_t; using m_range_t = daw::remove_cvrvref_t; - m_range_t m_range; + mutable m_range_t m_range; iterator_t m_range_first{ }; sub_iterator_t m_cur_first{ }; - [[nodiscard]] constexpr auto rabegin( ) { - return std::begin( m_range ); - } - [[nodiscard]] constexpr auto rabegin( ) const { return std::begin( m_range ); } - [[nodiscard]] constexpr iterator_end_t raend( ) { - return std::end( m_range ); - } - - [[nodiscard]] constexpr iterator_end_t raend( ) const { + [[nodiscard]] constexpr auto raend( ) const { return std::end( m_range ); } @@ -93,7 +85,10 @@ namespace daw::pipelines::pimpl { public: explicit flatten_view( ) = default; - explicit constexpr flatten_view( auto &&r ) + template + requires( not std::same_as, + flatten_view> ) // + explicit constexpr flatten_view( U &&r ) : m_range( DAW_FWD( r ) ) , m_range_first( rabegin( ) ) , m_cur_first( m_range_first == raend( ) @@ -104,7 +99,7 @@ namespace daw::pipelines::pimpl { return *this; } - [[nodiscard]] constexpr end_t end( ) const { + [[nodiscard]] constexpr auto end( ) const { return end_t{ raend( ) }; } @@ -152,7 +147,7 @@ namespace daw::pipelines::pimpl { } }; template - flatten_view( R && ) -> flatten_view; + flatten_view( R && ) -> flatten_view>; struct Flatten_t { [[nodiscard]] DAW_ATTRIB_INLINE DAW_CPP23_STATIC_CALL_OP constexpr auto diff --git a/include/daw/pipelines/map.h b/include/daw/pipelines/map.h index 7b5cb62cf..ae751f6cb 100644 --- a/include/daw/pipelines/map.h +++ b/include/daw/pipelines/map.h @@ -27,7 +27,7 @@ namespace daw::pipelines { struct map_iterator { using iterator_category = daw::iter_category_t; using value_type = daw::remove_cvref_t>>>; + Fn, std::invoke_result_t>>>; using reference = value_type; using const_reference = value_type; using pointer = arrow_proxy; @@ -238,9 +238,9 @@ namespace daw::pipelines { [[nodiscard]] constexpr auto operator( )( auto &&r ) const { using R = DAW_TYPEOF( r ); static_assert( - std::invocable>, + std::invocable>, "Projection must be invocable with the range_value_t" ); - using projected_t = std::invoke_result_t>; + using projected_t = std::invoke_result_t>; if constexpr( Range ) { static_assert( std::invocable, diff --git a/include/daw/pipelines/slide.h b/include/daw/pipelines/slide.h index 8be552291..1fa201c36 100644 --- a/include/daw/pipelines/slide.h +++ b/include/daw/pipelines/slide.h @@ -21,11 +21,11 @@ namespace daw::pipelines::pimpl { template struct slide_view { using iterator = daw::iterator_t; - using const_iterator = daw::iterator_t>; + using const_iterator = daw::const_iterator_t; using iterator_category = daw::range_category_t; using value_type = range_t; using reference = range_t; - using const_reference = range_t; + using const_reference = range_t; using difference_type = std::ptrdiff_t; using i_am_a_daw_slide_view_iterator_class = void; @@ -55,8 +55,10 @@ namespace daw::pipelines::pimpl { public: explicit slide_view( ) = default; - explicit slide_view( Range auto &&r ) - : m_range{ DAW_FWD( r ) } + template + requires( not std::same_as, slide_view> ) // + explicit slide_view( U &&r ) + : m_range( DAW_FWD( r ) ) , m_iter{ std::begin( m_range ) } {} explicit constexpr slide_view( Range auto &&r, std::size_t slide_size ) @@ -120,9 +122,9 @@ namespace daw::pipelines::pimpl { operator!=( slide_view const &rhs ) const noexcept = default; }; template - slide_view( R &&r ) -> slide_view; + slide_view( R &&r ) -> slide_view>; template - slide_view( R &&r, std::size_t ) -> slide_view; + slide_view( R &&r, std::size_t ) -> slide_view>; struct Slide_t { std::size_t slide_size = 1; diff --git a/tests/daw_pipelines_test.cpp b/tests/daw_pipelines_test.cpp index a8b182b42..dbc19f9cc 100644 --- a/tests/daw_pipelines_test.cpp +++ b/tests/daw_pipelines_test.cpp @@ -48,6 +48,7 @@ inline constexpr auto to_lower = []( char c ) -> char { }; namespace tests { + static constexpr auto prices = std::array{ 100, 200, 150, 180, 130 }; static constexpr auto costs = std::array{ 10, 20, 50, 40, 100 }; @@ -73,442 +74,442 @@ namespace tests { inline constexpr auto to_letter = ToLetter_t{ }; DAW_ATTRIB_NOINLINE void test002( ) { - constexpr auto pm2 = pipeline( Map( to_letter ), Enumerate, To ); - auto const m2 = pm2( iota_view( 0, 26 ) ); - daw::println( - "\ntest002: pipeline( Map( to_letter ), Enumerate, To )\n{}", - daw::fmt_range( m2 ) ); - - constexpr auto pm3 = - pipeline( Map( to_letter ), EnumerateWith, To ); - auto const m3 = pm3( iota_view( 0, 26 ) ); - daw::println( - "\ntest002: pipeline( Map( to_letter ), EnumerateWith, To " - ")\n{}", - daw::fmt_range( m3 ) ); - - for( auto vec = std::vector{ 1, 2, 3 }; - auto [index, value] : EnumerateWith( vec ) ) { - daw::dump( index * value ); - } + constexpr auto pm2 = pipeline( Map( to_letter ), Enumerate, To ); + auto const m2 = pm2( iota_view( 0, 26 ) ); + daw::println( + "\ntest002: pipeline( Map( to_letter ), Enumerate, To )\n{}", + daw::fmt_range( m2 ) ); + + constexpr auto pm3 = + pipeline( Map( to_letter ), EnumerateWith, To ); + auto const m3 = pm3( iota_view( 0, 26 ) ); + daw::println( + "\ntest002: pipeline( Map( to_letter ), EnumerateWith, To " + ")\n{}", + daw::fmt_range( m3 ) ); + + for( auto vec = std::vector{ 1, 2, 3 }; + auto [index, value] : EnumerateWith( vec ) ) { + daw::dump( index * value ); + } } DAW_ATTRIB_NOINLINE void test003( ) { - constexpr auto q = pipeline( Filter( Not( vowel ) ), - Take( 8 ), - Map( to_lower ), - Filter( is_letter ), - To, - Sort, - Unique, - Map( []( long long i ) { - return i; - } ), - Sum ); - auto const out0 = q( "Hello World, How are you?" ); - auto const out1 = q( "Blah blah blah, how is yah?" ); - daw::println( - "\ntest003: pipeline(\n\tFilter( Not( vowel ) ),\n\tTake( 8 ),\n\tMap( " - "to_lower ),Filter( is_letter " - "),\n\tTo,\n\tSort,\n\tUnique,\n\tMap( []( long " - "long " - "i ) {{ return i; }}),\n\tSum );" ); - daw::println( "\tinput 'Hello World, How are you?' - output {}", out0 ); - daw::println( "\tinput 'Blah blah blah, how is yah?' - output {}", out1 ); + constexpr auto q = pipeline( Filter( Not( vowel ) ), + Take( 8 ), + Map( to_lower ), + Filter( is_letter ), + To, + Sort, + Unique, + Map( []( long long i ) { + return i; + } ), + Sum ); + auto const out0 = q( "Hello World, How are you?" ); + auto const out1 = q( "Blah blah blah, how is yah?" ); + daw::println( + "\ntest003: pipeline(\n\tFilter( Not( vowel ) ),\n\tTake( 8 ),\n\tMap( " + "to_lower ),Filter( is_letter " + "),\n\tTo,\n\tSort,\n\tUnique,\n\tMap( []( long " + "long " + "i ) {{ return i; }}),\n\tSum );" ); + daw::println( "\tinput 'Hello World, How are you?' - output {}", out0 ); + daw::println( "\tinput 'Blah blah blah, how is yah?' - output {}", out1 ); } DAW_ATTRIB_NOINLINE void test004( ) { - constexpr auto p = pipeline( Filter( Not( vowel ) ), - Print, - Take( 8 ), - Print, - Map( to_lower ), - Print, - Filter( is_letter ) ); - constexpr auto p1 = pipeline( p, Take( 4 ) ); - daw::println( - "\ntest004: pipeline(Filter( Not( vowel ) ), Take( 8 ), Map( to_lower " - "), " - "Filter( is_letter ) )" ); - auto r0 = p1( "Hello World, How are you?" ); - auto r1 = p1( "Blah blah blah, how is yah?" ); - daw::println( "\tinput 'Hello World, How are you?': output {}", - daw::fmt_range( r0 ) ); - daw::println( "\tinput 'Blah blah blah, how is yah?': output {}", - daw::fmt_range( r1 ) ); + constexpr auto p = pipeline( Filter( Not( vowel ) ), + Print, + Take( 8 ), + Print, + Map( to_lower ), + Print, + Filter( is_letter ) ); + constexpr auto p1 = pipeline( p, Take( 4 ) ); + daw::println( + "\ntest004: pipeline(Filter( Not( vowel ) ), Take( 8 ), Map( to_lower " + "), " + "Filter( is_letter ) )" ); + auto r0 = p1( "Hello World, How are you?" ); + auto r1 = p1( "Blah blah blah, how is yah?" ); + daw::println( "\tinput 'Hello World, How are you?': output {}", + daw::fmt_range( r0 ) ); + daw::println( "\tinput 'Blah blah blah, how is yah?': output {}", + daw::fmt_range( r1 ) ); } DAW_ATTRIB_NOINLINE void test005( ) { - // Example from https://youtu.be/itnyR9j8y6E?t=404 - constexpr auto p3 = - pipeline( Map( []( auto i ) { - return std::pair{ i, std::to_string( i ) }; - } ), - Filter( []( auto const &v ) { - auto lhs = static_cast( v.first ); - auto const h = std::hash{ }( v.second ); - return lhs < h; - } ), - Map( &std::pair::second ), - Take( 4 ), - To> ); - auto const result = p3( iota_view( 1, 10001 ) ); - daw::println( "\ntest005: input 1 to 10001 : output {}", - daw::fmt_range( result ) ); + // Example from https://youtu.be/itnyR9j8y6E?t=404 + constexpr auto p3 = + pipeline( Map( []( auto i ) { + return std::pair{ i, std::to_string( i ) }; + } ), + Filter( []( auto const &v ) { + auto lhs = static_cast( v.first ); + auto const h = std::hash{ }( v.second ); + return lhs < h; + } ), + Map( &std::pair::second ), + Take( 4 ), + To> ); + auto const result = p3( iota_view( 1, 10001 ) ); + daw::println( "\ntest005: input 1 to 10001 : output {}", + daw::fmt_range( result ) ); } DAW_ATTRIB_NOINLINE void test006( ) { - auto const r2 = - pipeline( iota_view( 1, 10001 ), - Map( []( auto i ) { - return std::pair{ i, std::to_string( i ) }; - } ), - Filter( []( auto const &v ) { - auto lhs = static_cast( v.first ); - auto const h = std::hash{ }( v.second ); - return lhs >= h; - } ), - Map( &std::pair::second ), - Take( 4 ) ); - daw::println( "\ntest006: input 1 to 10001 : output {}", - daw::fmt_range( r2 ) ); + auto const r2 = + pipeline( iota_view( 1, 10001 ), + Map( []( auto i ) { + return std::pair{ i, std::to_string( i ) }; + } ), + Filter( []( auto const &v ) { + auto lhs = static_cast( v.first ); + auto const h = std::hash{ }( v.second ); + return lhs >= h; + } ), + Map( &std::pair::second ), + Take( 4 ) ); + daw::println( "\ntest006: input 1 to 10001 : output {}", + daw::fmt_range( r2 ) ); } consteval void test007( ) { - constexpr auto p4 = pipeline( Filter( []( int x ) { - return x % 2 == 0; - } ), - Map( []( std::optional x ) { - if( not x ) { - return iota_view{ 1 }; - } - return iota_view{ *x }; - } ), - Count, - ToIota, - Map( []( int x ) { - return x * 2; - } ) ); - constexpr auto x = p4( std::array{ 1, 2, 3 } ); - constexpr auto y = *std::next( x.begin( ) ); - static_assert( y == 2 ); + constexpr auto p4 = pipeline( Filter( []( int x ) { + return x % 2 == 0; + } ), + Map( []( std::optional x ) { + if( not x ) { + return iota_view{ 1 }; + } + return iota_view{ *x }; + } ), + Count, + ToIota, + Map( []( int x ) { + return x * 2; + } ) ); + constexpr auto x = p4( std::array{ 1, 2, 3 } ); + constexpr auto y = *std::next( x.begin( ) ); + static_assert( y == 2 ); } DAW_ATTRIB_NOINLINE void test008( ) { - daw::println( - "\ntest008: pipeline(\n\t\tMap( [](unsigned i) {{\n\t\t\treturn " - "std::tuple(i,to_letter(i));\n\t\t}} " - "),\n\t\tPrint,\n\t\tSwizzle<1,0,0>,\n\t\tPrint\n\t)\n\tinput 0 to 52: " - "output\n" ); - constexpr auto tp0 = pipeline( Map( []( unsigned i ) { - return std::tuple( i, to_letter( i ) ); - } ), - Print, - Swizzle<1, 0, 0>, - Print ); - (void)tp0( iota_view( 0, 52 ) ); + daw::println( + "\ntest008: pipeline(\n\t\tMap( [](unsigned i) {{\n\t\t\treturn " + "std::tuple(i,to_letter(i));\n\t\t}} " + "),\n\t\tPrint,\n\t\tSwizzle<1,0,0>,\n\t\tPrint\n\t)\n\tinput 0 to 52: " + "output\n" ); + constexpr auto tp0 = pipeline( Map( []( unsigned i ) { + return std::tuple( i, to_letter( i ) ); + } ), + Print, + Swizzle<1, 0, 0>, + Print ); + (void)tp0( iota_view( 0, 52 ) ); } DAW_ATTRIB_NOINLINE void test009( ) { - daw::println( - "\ntest009: pipeline( ZipMore( iota_view( 'A', 'Z' ) ) )" ); - constexpr auto tp1 = pipeline( ZipMore( iota_view( 'A', 'Z' ) ) ); + daw::println( + "\ntest009: pipeline( ZipMore( iota_view( 'A', 'Z' ) ) )" ); + constexpr auto tp1 = pipeline( ZipMore( iota_view( 'A', 'Z' ) ) ); - constexpr auto tp1r0 = tp1( iota_view( 'a', 'z' ) ); - daw::println( "\n\tinput: iota_view( 'a', 'z' ): output\n{}", - daw::fmt_range( tp1r0 ) ); + constexpr auto tp1r0 = tp1( iota_view( 'a', 'z' ) ); + daw::println( "\n\tinput: iota_view( 'a', 'z' ): output\n{}", + daw::fmt_range( tp1r0 ) ); - constexpr auto tp1r1 = tp1( - zip_view( iota_view( 'a', 'z' ), iota_view( 'a', 'z' ) ) ); - daw::println( - "\n\tinput:zip_view( iota_view( 'a', 'z' ), iota_view( " - "'a', " - "'z' ) ) : output\n{}", - daw::fmt_range( tp1r1 ) ); + constexpr auto tp1r1 = tp1( + zip_view( iota_view( 'a', 'z' ), iota_view( 'a', 'z' ) ) ); + daw::println( + "\n\tinput:zip_view( iota_view( 'a', 'z' ), iota_view( " + "'a', " + "'z' ) ) : output\n{}", + daw::fmt_range( tp1r1 ) ); } DAW_ATTRIB_NOINLINE void fma( std::size_t N, double const *__restrict a, double const *__restrict b, double const *__restrict c, double *__restrict out ) { - auto const fma_range = - pipeline( zip_view( daw::contiguous_view( a, N ), - daw::contiguous_view( b, N ), - daw::contiguous_view( c, N ) ), - MapApply( []( double x, double y, double z ) { - auto result = x + y * z; - return result; - } ) ); - static_assert( std::same_as, - std::random_access_iterator_tag> ); - auto first = std::begin( fma_range ); - auto const last = std::end( fma_range ); - while( first != last ) { - *out = *first; - ++out; - ++first; - } + auto const fma_range = + pipeline( zip_view( daw::contiguous_view( a, N ), + daw::contiguous_view( b, N ), + daw::contiguous_view( c, N ) ), + MapApply( []( double x, double y, double z ) { + auto result = x + y * z; + return result; + } ) ); + static_assert( std::same_as, + std::random_access_iterator_tag> ); + auto first = std::begin( fma_range ); + auto const last = std::end( fma_range ); + while( first != last ) { + *out = *first; + ++out; + ++first; + } } DAW_ATTRIB_NOINLINE void test010( ) { - daw::println( "\ntest010: fma test" ); - auto const make_random = - pipeline( Map( [rnd = daw::RandomFloat{ }]( auto ) mutable { - auto result = rnd( ); - return result; - } ), - To ); - std::vector const a = make_random( iota_view( 16 ) ); - daw::println( "\na: {}", daw::fmt_range( a ) ); - daw::do_not_optimize( a ); - std::vector const b = make_random( iota_view( 16 ) ); - daw::println( "\nb: {}", daw::fmt_range( b ) ); - daw::do_not_optimize( b ); - std::vector const c = make_random( iota_view( 16 ) ); - daw::println( "\nc: {}", daw::fmt_range( c ) ); - daw::do_not_optimize( c ); - auto o = std::vector( 16ULL ); - daw::do_not_optimize( o ); - fma( o.size( ), - std::data( a ), - std::data( b ), - std::data( c ), - std::data( o ) ); - daw::println( "\no: {}", daw::fmt_range( o ) ); - daw::do_not_optimize( o ); - daw_ensure( a[0] != o[0] ); + daw::println( "\ntest010: fma test" ); + auto const make_random = + pipeline( Map( [rnd = daw::RandomFloat{ }]( auto ) mutable { + auto result = rnd( ); + return result; + } ), + To ); + std::vector const a = make_random( iota_view( 16 ) ); + daw::println( "\na: {}", daw::fmt_range( a ) ); + daw::do_not_optimize( a ); + std::vector const b = make_random( iota_view( 16 ) ); + daw::println( "\nb: {}", daw::fmt_range( b ) ); + daw::do_not_optimize( b ); + std::vector const c = make_random( iota_view( 16 ) ); + daw::println( "\nc: {}", daw::fmt_range( c ) ); + daw::do_not_optimize( c ); + auto o = std::vector( 16ULL ); + daw::do_not_optimize( o ); + fma( o.size( ), + std::data( a ), + std::data( b ), + std::data( c ), + std::data( o ) ); + daw::println( "\no: {}", daw::fmt_range( o ) ); + daw::do_not_optimize( o ); + daw_ensure( a[0] != o[0] ); } DAW_ATTRIB_NOINLINE void test011( ) { - constexpr auto a = - std::array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; - constexpr auto p0 = pipeline( Skip( 1 ), Take( 5 ), To ); - auto v0 = p0( a ); - daw::println( - "\ntest011: pipeline( a, Skip( 1 ), Take( 5 ), To " - "):\n\tinput: " - "[1,2,3,4,5,6,7,8,9]\n\touput: {}", - daw::fmt_range( v0 ) ); + constexpr auto a = + std::array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + constexpr auto p0 = pipeline( Skip( 1 ), Take( 5 ), To ); + auto v0 = p0( a ); + daw::println( + "\ntest011: pipeline( a, Skip( 1 ), Take( 5 ), To " + "):\n\tinput: " + "[1,2,3,4,5,6,7,8,9]\n\touput: {}", + daw::fmt_range( v0 ) ); } DAW_ATTRIB_INLINE void test012( ) { - auto v = pipeline( iota_view( 1, 101 ), To> ); - daw::do_not_optimize( v ); - auto s = Sum( v ); - daw::println( - "\ntest012: pipeline( iota_view( 1, 101 ), To> " - ")\nSum: {} of\n{}", - s, - daw::fmt_range( v ) ); + auto v = pipeline( iota_view( 1, 101 ), To> ); + daw::do_not_optimize( v ); + auto s = Sum( v ); + daw::println( + "\ntest012: pipeline( iota_view( 1, 101 ), To> " + ")\nSum: {} of\n{}", + s, + daw::fmt_range( v ) ); } DAW_ATTRIB_NOINLINE void test013( ) { - static constexpr auto const v = pipeline( zip_view( prices, costs ), - MapApply( []( auto pr, auto co ) { - return pr - co; - } ), - Clamp( 5, 100 ), - To> ); - daw::println( "MapApply, Clamp, To\n{}", daw::fmt_range( v ) ); - constexpr auto v1 = pipeline( zip_view( prices, costs, v ), Concat ); - daw::println( "Concat\n{}", daw::fmt_range( v1 ) ); - - auto to_array = []( - daw::constant, C const &c ) { - using value_t = typename C::value_type; - return To>( )( c ); - }; - - constexpr auto pm = pipeline( Map( []( int i ) { - return std::pair{ i, to_letter( i ) }; - } ), - To ); - auto const m = pm( iota_view( 0, 26 ) ); - daw::println( "To\n{}", daw::fmt_range( m ) ); - auto va = to_array( daw::constant{ }, v ); - daw::println( "{}", daw::fmt_range( va ) ); + static constexpr auto const v = pipeline( zip_view( prices, costs ), + MapApply( []( auto pr, auto co ) { + return pr - co; + } ), + Clamp( 5, 100 ), + To> ); + daw::println( "MapApply, Clamp, To\n{}", daw::fmt_range( v ) ); + constexpr auto v1 = pipeline( zip_view( prices, costs, v ), Concat ); + daw::println( "Concat\n{}", daw::fmt_range( v1 ) ); + + auto to_array = []( + daw::constant, C const &c ) { + using value_t = typename C::value_type; + return To>( )( c ); + }; + + constexpr auto pm = pipeline( Map( []( int i ) { + return std::pair{ i, to_letter( i ) }; + } ), + To ); + auto const m = pm( iota_view( 0, 26 ) ); + daw::println( "To\n{}", daw::fmt_range( m ) ); + auto va = to_array( daw::constant{ }, v ); + daw::println( "{}", daw::fmt_range( va ) ); } void test014( ) { - daw::println( "\ntest014 - naive vs Kahan FP summation" ); - auto da = std::array{ 1024.123, - 0.000000013143, - 0.0001123434, - 4533.5, - 1.0, - 1.000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 0.0000000000000000001, - 1.657348632812501, - 1032.03423423 }; - auto s_kahan = SumKahanBabushkaNeumaier( da ); - daw::println( "{:.19f}\nThe Kahan sum is {:.19f}", - daw::fmt_range{ da, ",\n\t", "[\t", " ]" }, - s_kahan ); - auto s_naive = Sum( da ); - daw::println( "The naive sum is {:.19f}", s_naive ); + daw::println( "\ntest014 - naive vs Kahan FP summation" ); + auto da = std::array{ 1024.123, + 0.000000013143, + 0.0001123434, + 4533.5, + 1.0, + 1.000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 0.0000000000000000001, + 1.657348632812501, + 1032.03423423 }; + auto s_kahan = SumKahanBabushkaNeumaier( da ); + daw::println( "{:.19f}\nThe Kahan sum is {:.19f}", + daw::fmt_range{ da, ",\n\t", "[\t", " ]" }, + s_kahan ); + auto s_naive = Sum( da ); + daw::println( "The naive sum is {:.19f}", s_naive ); } DAW_ATTRIB_NOINLINE void test015( ) { - constexpr auto a = pipeline( generate_n( 5, - [i = 1]( ) mutable { - return i++; - } ), - To> ); - daw::println( - "\ntest015: pipeline( generate_n( 5, [&]{{return " - "i++;}}),To>);\n{}", - daw::fmt_range{ a } ); + constexpr auto a = pipeline( generate_n( 5, + [i = 1]( ) mutable { + return i++; + } ), + To> ); + daw::println( + "\ntest015: pipeline( generate_n( 5, [&]{{return " + "i++;}}),To>);\n{}", + daw::fmt_range{ a } ); } DAW_ATTRIB_NOINLINE void test016( ) { - constexpr auto a = - std::array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; - constexpr auto p0 = pipeline( Skip( 3 ), To ); - auto v0 = p0( a ); - daw::println( - "\ntest016: pipeline( a, Skip( 3 ), To ):\n\tinput: " - "[1,2,3,4,5,6,7,8,9]\n\touput: {}", - daw::fmt_range( v0 ) ); + constexpr auto a = + std::array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + constexpr auto p0 = pipeline( Skip( 3 ), To ); + auto v0 = p0( a ); + daw::println( + "\ntest016: pipeline( a, Skip( 3 ), To ):\n\tinput: " + "[1,2,3,4,5,6,7,8,9]\n\touput: {}", + daw::fmt_range( v0 ) ); } DAW_ATTRIB_NOINLINE void test017( ) { - daw::println( - "\ntest017: pipeline( iota_view{{ -5, 5 }}, Sample( 4, 10 ) )" ); - auto const p = pipeline( iota_view{ -5, 5 }, Print, Sample( 4, 10 ) ); - daw::println( "{}", daw::fmt_range{ p } ); + daw::println( + "\ntest017: pipeline( iota_view{{ -5, 5 }}, Sample( 4, 10 ) )" ); + auto const p = pipeline( iota_view{ -5, 5 }, Print, Sample( 4, 10 ) ); + daw::println( "{}", daw::fmt_range{ p } ); } DAW_ATTRIB_NOINLINE void test018( ) { - daw::println( "\ntest018: pipeline( iota_view{{ -5, 5 }}, Reverse )" ); - auto i = iota_view{ -5, 5 }; - daw::println( "\t{}", daw::fmt_range( i ) ); - daw::println( "\treversed" ); - daw::println( "\t{}", daw::fmt_range( Reverse( i ) ) ); + daw::println( "\ntest018: pipeline( iota_view{{ -5, 5 }}, Reverse )" ); + auto i = iota_view{ -5, 5 }; + daw::println( "\t{}", daw::fmt_range( i ) ); + daw::println( "\treversed" ); + daw::println( "\t{}", daw::fmt_range( Reverse( i ) ) ); } DAW_ATTRIB_NOINLINE void test019( ) { - daw::println( - "\ntest019: pipeline( iota_view{{ -5, 5 }}, Every( 3 ) )" ); - auto const p = pipeline( iota_view{ -5, 5 }, Print, Every( 3 ) ); - daw::println( "{}", daw::fmt_range{ p } ); + daw::println( + "\ntest019: pipeline( iota_view{{ -5, 5 }}, Every( 3 ) )" ); + auto const p = pipeline( iota_view{ -5, 5 }, Print, Every( 3 ) ); + daw::println( "{}", daw::fmt_range{ p } ); } DAW_ATTRIB_NOINLINE void test020( ) { - daw::println( - "\ntest020: pipeline( iota_view{{ -5, 5 }}, TakeUntil( []( int x ) " - "{{ return x > 0; }} ) ) )" ); - daw::println( "\tin: {}", daw::fmt_range{ iota_view{ -5, 5 } } ); - auto const p = pipeline( iota_view{ -5, 5 }, TakeUntil( []( int x ) { - return x > 0; - } ) ); - daw::println( "\tout: {}", daw::fmt_range{ p } ); + daw::println( + "\ntest020: pipeline( iota_view{{ -5, 5 }}, TakeUntil( []( int x ) " + "{{ return x > 0; }} ) ) )" ); + daw::println( "\tin: {}", daw::fmt_range{ iota_view{ -5, 5 } } ); + auto const p = pipeline( iota_view{ -5, 5 }, TakeUntil( []( int x ) { + return x > 0; + } ) ); + daw::println( "\tout: {}", daw::fmt_range{ p } ); } DAW_ATTRIB_NOINLINE void test021( ) { - daw::println( - "\ntest021: pipeline( iota_view{{ -5, 5 }}, TakeWhile( []( int x ) " - "{{ return x < 0; }} ) ) )" ); - daw::println( "\tin: {}", daw::fmt_range{ iota_view{ -5, 5 } } ); - auto const p = pipeline( iota_view{ -5, 5 }, TakeWhile( []( int x ) { - return x < 0; - } ) ); - daw::println( "\tout: {}", daw::fmt_range{ p } ); + daw::println( + "\ntest021: pipeline( iota_view{{ -5, 5 }}, TakeWhile( []( int x ) " + "{{ return x < 0; }} ) ) )" ); + daw::println( "\tin: {}", daw::fmt_range{ iota_view{ -5, 5 } } ); + auto const p = pipeline( iota_view{ -5, 5 }, TakeWhile( []( int x ) { + return x < 0; + } ) ); + daw::println( "\tout: {}", daw::fmt_range{ p } ); } DAW_ATTRIB_NOINLINE void test022( ) { - daw::println( "\ntest022: pipeline( Print, Flatten, Print )" ); - constexpr auto ary = std::array{ iota_view{ 1, 2 }, - iota_view{ 6, 10 }, - iota_view{ 15, 17 } }; - auto r = pipeline( ary, Print, Flatten, Print ); - (void)r; + daw::println( "\ntest022: pipeline( Print, Flatten, Print )" ); + constexpr auto ary = std::array{ iota_view{ 1, 2 }, + iota_view{ 6, 10 }, + iota_view{ 15, 17 } }; + auto r = pipeline( ary, Print, Flatten, Print ); + (void)r; } DAW_ATTRIB_NOINLINE void test023( ) { - static constexpr auto ary = - To>( )( iota_view( 9 ) ); - daw::println( "\ntest023: pipeline( Chunk( 3 ), Flatten )" ); - daw::println( "\tin: {}", daw::fmt_range( ary ) ); - constexpr auto p = pipeline( Chunk( 3 ), Print, Flatten ); - auto r = p( ary ); - auto const ary2 = To>( )( r ); - daw_ensure( ary == ary2 ); - daw::println( "\tout: {}", daw::fmt_range( ary2 ) ); + static constexpr auto ary = + To>( )( iota_view( 9 ) ); + daw::println( "\ntest023: pipeline( Chunk( 3 ), Flatten )" ); + daw::println( "\tin: {}", daw::fmt_range( ary ) ); + constexpr auto p = pipeline( Chunk( 3 ), Print, Flatten ); + auto r = p( ary ); + auto const ary2 = To>( )( r ); + daw_ensure( ary == ary2 ); + daw::println( "\tout: {}", daw::fmt_range( ary2 ) ); } DAW_ATTRIB_NOINLINE void test024( ) { - static constexpr auto ary = std::array{ 1, 2, 3, 4, 4, 5, 6, 6, 7 }; - constexpr auto it = FindIf<2>( ary, []( auto const &l, auto const &r ) { - return l == r; - } ); - static_assert( it != std::end( ary ) ); - static_assert( std::distance( std::begin( ary ), it ) == 3 ); + static constexpr auto ary = std::array{ 1, 2, 3, 4, 4, 5, 6, 6, 7 }; + constexpr auto it = FindIf<2>( ary, []( auto const &l, auto const &r ) { + return l == r; + } ); + static_assert( it != std::end( ary ) ); + static_assert( std::distance( std::begin( ary ), it ) == 3 ); - constexpr auto it2 = Find( ary, 2 ); - static_assert( it2 != std::end( ary ) ); - static_assert( std::distance( std::begin( ary ), it2 ) == 1 ); - constexpr auto it3 = Find( 2 )( ary ); - static_assert( it2 == it3 ); + constexpr auto it2 = Find( ary, 2 ); + static_assert( it2 != std::end( ary ) ); + static_assert( std::distance( std::begin( ary ), it2 ) == 1 ); + constexpr auto it3 = Find( 2 )( ary ); + static_assert( it2 == it3 ); } DAW_ATTRIB_NOINLINE void test025( ) { - struct Test { - int value; - - explicit( false ) constexpr Test( int v ) - : value( v ) {} - }; - static constexpr auto ary = - std::array{ 1, 2, 3, 4, 4, 5, 6, 6, 7 }; - constexpr auto it = FindIf<2>( ary, []( auto const &l, auto const &r ) { - return l.value == r.value; - } ); - static_assert( it != std::end( ary ) ); - static_assert( std::distance( std::begin( ary ), it ) == 3 ); - - constexpr auto it2 = Find( ary, 2, &Test::value ); - static_assert( it2 != std::end( ary ) ); - static_assert( std::distance( std::begin( ary ), it2 ) == 1 ); - constexpr auto it3 = Find( 2, &Test::value )( ary ); - static_assert( it2 == it3 ); + struct Test { + int value; + + explicit( false ) constexpr Test( int v ) + : value( v ) {} + }; + static constexpr auto ary = + std::array{ 1, 2, 3, 4, 4, 5, 6, 6, 7 }; + constexpr auto it = FindIf<2>( ary, []( auto const &l, auto const &r ) { + return l.value == r.value; + } ); + static_assert( it != std::end( ary ) ); + static_assert( std::distance( std::begin( ary ), it ) == 3 ); + + constexpr auto it2 = Find( ary, 2, &Test::value ); + static_assert( it2 != std::end( ary ) ); + static_assert( std::distance( std::begin( ary ), it2 ) == 1 ); + constexpr auto it3 = Find( 2, &Test::value )( ary ); + static_assert( it2 == it3 ); } DAW_ATTRIB_NOINLINE void test026( ) { - static constexpr auto ary = - To>( )( iota_view( 9 ) ); - daw::println( "\ntest026: pipeline( Slide( 3 ), Flatten )" ); - daw::println( "\tin: {}", daw::fmt_range( ary ) ); - constexpr auto p = pipeline( Slide( 3 ), Print, Flatten ); - auto r = p( ary ); - auto const ary2 = To>( )( r ); - constexpr auto tst_ary = - std::array{ 0, 1, 2, 1, 2, 3, 2, 3, 4 }; - daw_ensure( ary2 == tst_ary ); - daw::println( "\tout: {}", daw::fmt_range( ary2 ) ); + static constexpr auto ary = + To>( )( iota_view( 9 ) ); + daw::println( "\ntest026: pipeline( Slide( 3 ), Flatten )" ); + daw::println( "\tin: {}", daw::fmt_range( ary ) ); + constexpr auto p = pipeline( Slide( 3 ), Print, Flatten ); + auto r = p( ary ); + auto const ary2 = To>( )( r ); + constexpr auto tst_ary = + std::array{ 0, 1, 2, 1, 2, 3, 2, 3, 4 }; + daw_ensure( ary2 == tst_ary ); + daw::println( "\tout: {}", daw::fmt_range( ary2 ) ); } DAW_ATTRIB_NOINLINE void test027( ) { - static constexpr std::array ids = { "597216680271282192"_sv, - "155149108183695360"_sv, - "843841057833877588"_sv, - "1013956772245020774"_sv, - "1013960757127422113"_sv }; - static constexpr auto exists = []( daw::string_view needle ) { - return Contains( needle )( ids ); - }; - constexpr auto x = "12345"_sv; - static_assert( not exists( x ) ); - constexpr auto y = "1013960757127422113"_sv; - static_assert( exists( y ) ); + static constexpr std::array ids = { "597216680271282192"_sv, + "155149108183695360"_sv, + "843841057833877588"_sv, + "1013956772245020774"_sv, + "1013960757127422113"_sv }; + static constexpr auto exists = []( daw::string_view needle ) { + return Contains( needle )( ids ); + }; + constexpr auto x = "12345"_sv; + static_assert( not exists( x ) ); + constexpr auto y = "1013960757127422113"_sv; + static_assert( exists( y ) ); } DAW_ATTRIB_NOINLINE void test028( ) { @@ -605,6 +606,16 @@ namespace tests { constexpr auto s2 = daw::string_view{ std::data( p ), std::size( p ) }; daw_ensure( s2 == "Hello" ); } + + DAW_ATTRIB_NOINLINE void test034( ) { + auto v = std::vector{ "Hello", "World" }; + + auto mapper = Map( +[]( std::string &s ) -> char * { + return s.data( ); + } ); + auto v2 = std::vector( std::from_range, mapper( v ) ); + daw_ensure( v2.size( ) == v.size( ) ); + } } // namespace tests int main( ) { @@ -641,6 +652,7 @@ int main( ) { tests::test031( ); tests::test032( ); tests::test033( ); + tests::test034( ); daw::println( "Done" ); }