2
0
mirror of https://github.com/boostorg/lambda2.git synced 2026-01-20 04:32:44 +00:00

Compare commits

..

14 Commits

Author SHA1 Message Date
Peter Dimov
08b40af530 Fix stream detection in op<<, op>> 2021-09-05 03:06:33 +03:00
Peter Dimov
d6389b60f5 Update tests with std::ref(is), std::ref(os) 2021-09-05 03:01:31 +03:00
Peter Dimov
f2ab3ade7c Update documentation 2021-09-05 02:53:33 +03:00
Peter Dimov
e2251ab450 Special-case streams in operator<< and operator>> 2021-09-05 01:50:37 +03:00
Peter Dimov
3a06c98e8d Update README 2021-09-05 01:19:08 +03:00
Peter Dimov
8b08326f6e Remove ubuntu-16.04 jobs from ci.yml 2021-09-05 01:18:52 +03:00
Peter Dimov
b9cc0aa5d1 Update README 2021-09-05 01:11:26 +03:00
Peter Dimov
58c947fcf9 Update version 2021-08-17 15:13:06 +03:00
Peter Dimov
9e2e0a31b3 Update copyright 2021-07-11 16:52:18 +03:00
Peter Dimov
93c67a57c8 Update reference 2021-07-11 16:51:40 +03:00
Peter Dimov
3bf3ce3a9e Update copyright 2021-07-11 16:28:39 +03:00
Peter Dimov
51b9448ae7 Update doc/.gitignore 2021-07-11 16:27:09 +03:00
Peter Dimov
a064c3ae83 Remove doc/html/lambda2.html 2021-07-11 16:25:58 +03:00
Peter Dimov
a329989b1e Update overview 2021-07-11 16:25:08 +03:00
13 changed files with 330 additions and 1092 deletions

View File

@@ -17,24 +17,13 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: gcc-4.7
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.7
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.8
- toolset: gcc-4.9
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.9
- toolset: gcc-5
cxxstd: "03,11,14,1z"
os: ubuntu-16.04
os: ubuntu-18.04
install: g++-5
- toolset: gcc-6
cxxstd: "03,11,14,1z"
os: ubuntu-16.04
os: ubuntu-18.04
install: g++-6
- toolset: gcc-7
cxxstd: "03,11,14,17"
@@ -45,7 +34,7 @@ jobs:
install: g++-8
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
os: ubuntu-20.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
@@ -53,40 +42,20 @@ jobs:
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
install: g++-11
- toolset: clang
compiler: clang++-3.5
cxxstd: "03,11"
os: ubuntu-16.04
install: clang-3.5
- toolset: clang
compiler: clang++-3.6
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.6
- toolset: clang
compiler: clang++-3.7
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.7
- toolset: clang
compiler: clang++-3.8
cxxstd: "03,11,14"
os: ubuntu-16.04
install: clang-3.8
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-16.04
os: ubuntu-18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0

View File

@@ -5,15 +5,15 @@ described in [this post](https://pdimov.github.io/blog/2020/07/22/a-c14-lambda-l
It has no dependencies and consists of a [single header](include/boost/lambda2/lambda2.hpp).
See [the documentation](https://www.boost.org/doc/libs/develop/libs/lambda2/) for more information.
See [the documentation](https://www.boost.org/libs/lambda2/) for more information.
## Supported Compilers
* g++ 5 or later with `-std=c++14` or above
* clang++ 3.5 or later with `-std=c++14` or above
* clang++ 3.9 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
Tested on [Travis](https://travis-ci.org/github/pdimov/lambda2/) and
Tested on [Github Actions](https://github.com/boostorg/lambda2/actions) and
[Appveyor](https://ci.appveyor.com/project/pdimov/lambda2).
## License

1
doc/.gitignore vendored
View File

@@ -1 +1,2 @@
/pdf/
/html/

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,7 @@ Peter Dimov
:leveloffset: +1
include::lambda2/overview.adoc[]
include::lambda2/changelog.adoc[]
include::lambda2/reference.adoc[]
include::lambda2/copyright.adoc[]

View File

@@ -0,0 +1,14 @@
////
Copyright 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
[#changelog]
# Revision History
:idprefix:
## Changes in 1.78.0
* Added special cases in `operator<<` and `operator>>` when
the first argument is a stream, to allow `std::cout << _1`.

View File

@@ -8,5 +8,5 @@ https://www.boost.org/LICENSE_1_0.txt
# Copyright and License
:idprefix:
This documentation is copyright 2020 Peter Dimov and is distributed under
This documentation is copyright 2020, 2021 Peter Dimov and is distributed under
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -12,16 +12,18 @@ https://www.boost.org/LICENSE_1_0.txt
This is a simple, but functional, {cpp}14 lambda library. It takes
advantage of the fact that the standard `<functional>` header already
provides placeholders `_1`, `_2`, `_3`, and so on, for use with
`std::bind`, and function objects such as `std::plus`, `std::greater`,
`std::logical_not`, and `std::bit_xor`, corresponding to arithmetic,
relational, logical and bitwise operators.
provides `std::bind` customization points (`is_placeholder`,
`is_bind_expression`), and function objects such as `std::plus`,
`std::greater`, `std::logical_not`, and `std::bit_xor`, corresponding
to arithmetic, relational, logical and bitwise operators.
This allows the library to provide a minimal implementation that
still lets expressions such as `_1 + 5`, `_1 % 2 == 0`, `_1 > _2`,
or `_1 == ' ' || _1 == '\t'` to be composed and used as function
objects.
For example, `_1 + 5` is implemented as `std::bind(std::plus<>, _1, 5)`.
These "lambda" expressions can also be freely combined with `std::bind`.
For example, `std::bind( f, _1 ) == std::bind( g, _1 )` and
`std::bind( f, _1 + _2 )` both work and have the expected behavior.
@@ -64,8 +66,8 @@ None. A single, self-contained header.
## Supported Compilers
* GCC 5 or later with `-std=c++14` or above
* Clang 3.5 or later with `-std=c++14` or above
* Clang 3.9 or later with `-std=c++14` or above
* Visual Studio 2015, 2017, 2019
Tested on https://travis-ci.org/github/pdimov/lambda2[Travis] and
Tested on https://github.com/boostorg/lambda2/actions[Github Actions] and
https://ci.appveyor.com/project/pdimov/lambda2[Appveyor].

View File

@@ -1,5 +1,5 @@
////
Copyright 2020 Peter Dimov
Copyright 2020, 2021 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
@@ -16,6 +16,22 @@ https://www.boost.org/LICENSE_1_0.txt
namespace boost {
namespace lambda2 {
// placeholders
template<int I> struct lambda2_arg;
inline constexpr lambda2_arg<1> _1{};
inline constexpr lambda2_arg<1> _2{};
inline constexpr lambda2_arg<1> _3{};
inline constexpr lambda2_arg<1> _4{};
inline constexpr lambda2_arg<1> _5{};
inline constexpr lambda2_arg<1> _6{};
inline constexpr lambda2_arg<1> _7{};
inline constexpr lambda2_arg<1> _8{};
inline constexpr lambda2_arg<1> _9{};
// arithmetic operators
template<class A, class B> auto operator+( A && a, B && b );
template<class A, class B> auto operator-( A && a, B && b );
template<class A, class B> auto operator*( A && a, B && b );
@@ -23,6 +39,8 @@ template<class A, class B> auto operator/( A && a, B && b );
template<class A, class B> auto operator%( A && a, B && b );
template<class A> auto operator-( A && a );
// relational operators
template<class A, class B> auto operator==( A && a, B && b );
template<class A, class B> auto operator!=( A && a, B && b );
template<class A, class B> auto operator>( A && a, B && b );
@@ -30,19 +48,84 @@ template<class A, class B> auto operator<( A && a, B && b );
template<class A, class B> auto operator>=( A && a, B && b );
template<class A, class B> auto operator<=( A && a, B && b );
// logical operators
template<class A, class B> auto operator&&( A && a, B && b );
template<class A, class B> auto operator||( A && a, B && b );
template<class A> auto operator!( A && a );
// bitwise operators
template<class A, class B> auto operator&( A && a, B && b );
template<class A, class B> auto operator|( A && a, B && b );
template<class A, class B> auto operator^( A && a, B && b );
template<class A> auto operator~( A && a );
template<class A, class B> auto operator<<( A && a, B && b );
template<class A, class B> auto operator>>( A && a, B && b );
// additional unary operators
template<class A> auto operator+( A && a );
template<class A> auto operator*( A && a );
template<class A> auto operator++( A && a );
template<class A> auto operator--( A && a );
template<class A> auto operator++( A && a, int );
template<class A> auto operator--( A && a, int );
// compound assignment operators
template<class A, class B> auto operator+=( A && a, B && b );
template<class A, class B> auto operator-=( A && a, B && b );
template<class A, class B> auto operator*=( A && a, B && b );
template<class A, class B> auto operator/=( A && a, B && b );
template<class A, class B> auto operator%=( A && a, B && b );
template<class A, class B> auto operator&=( A && a, B && b );
template<class A, class B> auto operator|=( A && a, B && b );
template<class A, class B> auto operator^=( A && a, B && b );
template<class A, class B> auto operator<<=( A && a, B && b );
template<class A, class B> auto operator>>=( A && a, B && b );
} // namespace lambda2
} // namespace boost
```
### Placeholders
```
template<int I> struct lambda2_arg
{
template<class... A> decltype(auto) operator()( A&&... a ) const noexcept;
template<class T> auto operator[]( T&& t ) const;
};
```
`lambda2_arg<I>` is the type of the library-provided placeholders `_I`. The
standard customization point `std::is_placeholder` is specialized for it,
enabling the use of Lambda2's placeholders with `std::bind`.
The placeholders define `operator()`, which permits their direct use as
function objects. E.g. `_1(x, y)` returns `x`.
`operator[]` is also defined to allow expressions like `_1[x]` or `_1[_2]`.
```
template<class... A> decltype(auto) operator()( A&&... a ) const noexcept;
```
[none]
* {blank}
+
Returns: :: `std::get<std::size_t{I-1}>( std::tuple<A&&...>( std::forward<A>(a)... ) );`
```
template<class T> auto operator[]( T&& t ) const;
```
[none]
* {blank}
+
Returns: :: `std::bind( fn, *this, std::forward<T>(t) );`, where `fn` is
a function object such that `fn(x, y)` returns `x[y]`.
### Common Requirements
All operators defined in the subsequent sections only participate in
@@ -214,3 +297,94 @@ template<class A> auto operator~( A && a );
+
Returns: ::
`std::bind( std::bit_not<>(), std::forward<A>(a) );`
```
template<class A, class B> auto operator<<( A && a, B && b );
```
[none]
* {blank}
+
Returns: :: `std::bind( fn, std::forward<A>(a), std::forward<B>(b) );`,
where `fn` is a function object such that `fn(x, y)` returns `x << y`.
```
template<class A, class B> auto operator>>( A && a, B && b );
```
[none]
* {blank}
+
Returns: :: `std::bind( fn, std::forward<A>(a), std::forward<B>(b) );`,
where `fn` is a function object such that `fn(x, y)` returns `x >> y`.
### Additional Unary Operators
```
template<class A> auto operator+( A && a );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `+x`.
```
template<class A> auto operator*( A && a );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `*x`.
```
template<class A> auto operator++( A && a );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `++x`.
```
template<class A> auto operator--( A && a );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `--x`.
```
template<class A> auto operator++( A && a, int );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `x++`.
```
template<class A> auto operator--( A && a, int );
```
[none]
* {blank}
+
Returns: ::
`std::bind( fn, std::forward<A>(a) );`, where `fn` is a function object
such that `fn(x)` returns `x--`.
### Compound Assignment Operators
```
template<class A, class B> auto operator@=( A && a, B && b );
```
[none]
* {blank}
+
Returns: :: `std::bind( fn, std::forward<A>(a), std::forward<B>(b) );`,
where `fn` is a function object such that `fn(x, y)` returns `x @= y`.

View File

@@ -1,7 +1,7 @@
#ifndef BOOST_LAMBDA2_LAMBDA2_HPP_INCLUDED
#define BOOST_LAMBDA2_LAMBDA2_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -10,10 +10,11 @@
#include <utility>
#include <tuple>
#include <cstddef>
#include <iosfwd>
// Same format as BOOST_VERSION:
// major * 100000 + minor * 100 + patch
#define BOOST_LAMBDA2_VERSION 107700
#define BOOST_LAMBDA2_VERSION 107800
namespace boost
{
@@ -151,6 +152,8 @@ template<class A> using enable_unary_lambda =
template<class A, class B> using enable_binary_lambda =
std::enable_if_t<is_lambda_expression<A>::value || is_lambda_expression<B>::value>;
template<class T> using is_stream = std::is_base_of<std::ios_base, remove_cvref_t<T>>;
} // namespace lambda2_detail
#define BOOST_LAMBDA2_UNARY_LAMBDA(op, fn) \
@@ -201,9 +204,6 @@ BOOST_LAMBDA2_UNARY_LAMBDA(~, std::bit_not<>)
// additional
BOOST_LAMBDA2_BINARY_LAMBDA(<<, lambda2_detail::left_shift)
BOOST_LAMBDA2_BINARY_LAMBDA(>>, lambda2_detail::right_shift)
BOOST_LAMBDA2_UNARY_LAMBDA(+, lambda2_detail::unary_plus)
BOOST_LAMBDA2_UNARY_LAMBDA(*, lambda2_detail::dereference)
@@ -226,6 +226,38 @@ BOOST_LAMBDA2_BINARY_LAMBDA(^=, lambda2_detail::bit_xor_equal)
BOOST_LAMBDA2_BINARY_LAMBDA(<<=, lambda2_detail::left_shift_equal)
BOOST_LAMBDA2_BINARY_LAMBDA(>>=, lambda2_detail::right_shift_equal)
// operator<<
template<class A, class = std::enable_if_t<!lambda2_detail::is_stream<A>::value>,
class B, class = lambda2_detail::enable_binary_lambda<A, B>>
auto operator<<( A&& a, B&& b )
{
return std::bind( lambda2_detail::left_shift(), std::forward<A>(a), std::forward<B>(b) ); \
}
template<class A, class = std::enable_if_t<lambda2_detail::is_stream<A>::value>,
class B, class = lambda2_detail::enable_unary_lambda<B>>
auto operator<<( A& a, B&& b )
{
return std::bind( lambda2_detail::left_shift(), std::ref(a), std::forward<B>(b) );
}
// operator>>
template<class A, class = std::enable_if_t<!lambda2_detail::is_stream<A>::value>,
class B, class = lambda2_detail::enable_binary_lambda<A, B>>
auto operator>>( A&& a, B&& b )
{
return std::bind( lambda2_detail::right_shift(), std::forward<A>(a), std::forward<B>(b) ); \
}
template<class A, class = std::enable_if_t<lambda2_detail::is_stream<A>::value>,
class B, class = lambda2_detail::enable_unary_lambda<B>>
auto operator>>( A& a, B&& b )
{
return std::bind( lambda2_detail::right_shift(), std::ref(a), std::forward<B>(b) );
}
} // namespace lambda2
} // namespace boost

View File

@@ -24,3 +24,5 @@ run placeholders.cpp ;
run increment.cpp ;
run subscript.cpp ;
run compound.cpp ;
run stream_insert.cpp ;
run stream_extract.cpp ;

42
test/stream_extract.cpp Normal file
View File

@@ -0,0 +1,42 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda2.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
#include <string>
template<class T> T from_string_1( std::string const& s )
{
using namespace boost::lambda2;
std::istringstream is( s );
T t{};
( std::ref( is ) >> _1 )( t );
return t;
}
template<class T> T from_string_2( std::string const& s )
{
using namespace boost::lambda2;
std::istringstream is( s );
T t{};
( is >> _1 )( t );
return t;
}
int main()
{
BOOST_TEST_EQ( from_string_1<int>( "123" ), 123 );
BOOST_TEST_EQ( from_string_2<int>( "456" ), 456 );
return boost::report_errors();
}

38
test/stream_insert.cpp Normal file
View File

@@ -0,0 +1,38 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/lambda2.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
#include <string>
template<class T> std::string to_string_1( T const& t )
{
using namespace boost::lambda2;
std::ostringstream os;
( std::ref( os ) << _1 )( t );
return os.str();
}
template<class T> std::string to_string_2( T const& t )
{
using namespace boost::lambda2;
std::ostringstream os;
( os << _1 )( t );
return os.str();
}
int main()
{
BOOST_TEST_EQ( to_string_1( 123 ), "123" );
BOOST_TEST_EQ( to_string_2( 456 ), "456" );
return boost::report_errors();
}