diff --git a/doc/core.qbk b/doc/core.qbk index df6330d..8926612 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -55,6 +55,7 @@ criteria for inclusion is that the utility component be: [include exchange.qbk] [include explicit_operator_bool.qbk] [include first_scalar.qbk] +[include identity.qbk] [include ignore_unused.qbk] [include is_same.qbk] [include launder.qbk] diff --git a/doc/identity.qbk b/doc/identity.qbk new file mode 100644 index 0000000..db03012 --- /dev/null +++ b/doc/identity.qbk @@ -0,0 +1,61 @@ +[/ +Copyright 2021-2023 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:identity identity] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +The header provides the function object +`boost::identity` whose `operator()` returns its argument. It is an +implementation of C++20's `std::identity` that supports C++03 and above. + +[endsect] + +[section Example] + +It is commonly used as the default projection in constrained algorithms. + +``` +template +void print(Range&& range, Projection projection = {}); +``` + +[endsect] + +[section Reference] + +``` +namespace boost { + +struct identity { + using is_transparent = unspecified; + + template + T&& operator()(T&& value) const noexcept; +}; + +} /* boost */ +``` + +[section Operators] + +[variablelist +[[`template T&& operator()(T&& value) const noexcept;`] +[Returns `std::forward(value)`.]]] + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/identity.hpp b/include/boost/core/identity.hpp new file mode 100644 index 0000000..f27733b --- /dev/null +++ b/include/boost/core/identity.hpp @@ -0,0 +1,61 @@ +/* +Copyright 2021-2023 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_IDENTITY_HPP +#define BOOST_CORE_IDENTITY_HPP + +#include +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include +#endif + +namespace boost { + +struct identity { + typedef void is_transparent; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + BOOST_CONSTEXPR T&& operator()(T&& value) const BOOST_NOEXCEPT { + return std::forward(value); + } +#else + template + BOOST_CONSTEXPR const T& operator()(const T& value) const BOOST_NOEXCEPT { + return value; + } + + template + BOOST_CONSTEXPR T& operator()(T& value) const BOOST_NOEXCEPT { + return value; + } +#endif + + template + struct result { }; + + template + struct result { + typedef T& type; + }; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + struct result { + typedef T&& type; + }; + + template + struct result { + typedef T&& type; + }; +#endif +}; + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 956ee36..bf50d5b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -368,5 +368,8 @@ run serialization_split_free_test.cpp : : : /boost//serialization//boost//serialization/off ; run serialization_construct_data_test.cpp : : : /boost//serialization/off ; +run identity_test.cpp ; +run identity_rvalue_test.cpp ; + use-project /boost/core/swap : ./swap ; build-project ./swap ; diff --git a/test/identity_rvalue_test.cpp b/test/identity_rvalue_test.cpp new file mode 100644 index 0000000..5cd4e9b --- /dev/null +++ b/test/identity_rvalue_test.cpp @@ -0,0 +1,69 @@ +/* +Copyright 2021-2023 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include +#include +#include +#include +#include +#include + +bool test(std::string&&) +{ + return true; +} + +bool test(const std::string&&) +{ + return true; +} + +template +bool test(T&&) +{ + return false; +} + +void simple_test() +{ + typedef std::string string; + BOOST_TEST(boost::identity()(string("a")) == string("a")); + BOOST_TEST(test(boost::identity()(string("a")))); + typedef const std::string cstring; + BOOST_TEST(boost::identity()(cstring("a")) == cstring("a")); + BOOST_TEST(test(boost::identity()(cstring("a")))); +} + +void algorithm_test() +{ + std::vector v1; + v1.push_back(std::string("a")); + v1.push_back(std::string("b")); + v1.push_back(std::string("c")); + std::vector v2(v1); + std::vector v3; + std::transform(std::make_move_iterator(v2.begin()), + std::make_move_iterator(v2.end()), + std::back_inserter(v3), + boost::identity()); + BOOST_TEST(v3 == v1); +} + +int main() +{ + simple_test(); + algorithm_test(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/test/identity_test.cpp b/test/identity_test.cpp new file mode 100644 index 0000000..e82e450 --- /dev/null +++ b/test/identity_test.cpp @@ -0,0 +1,66 @@ +/* +Copyright 2021-2023 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include +#include +#include + +bool test(std::string&) +{ + return true; +} + +bool test(const std::string&) +{ + return true; +} + +template +bool test(T&) +{ + return false; +} + +template +bool test(const T&) +{ + return false; +} + +void simple_test() +{ + std::string s1("a"); + BOOST_TEST(boost::identity()(s1) == s1); + BOOST_TEST(&boost::identity()(s1) == &s1); + BOOST_TEST(test(boost::identity()(s1))); + const std::string s2("a"); + BOOST_TEST(boost::identity()(s2) == s2); + BOOST_TEST(&boost::identity()(s2) == &s2); + BOOST_TEST(test(boost::identity()(s2))); +} + +void algorithm_test() +{ + std::vector v1; + v1.push_back(std::string("a")); + v1.push_back(std::string("b")); + v1.push_back(std::string("c")); + std::vector v2; + std::transform(v1.begin(), v1.end(), std::back_inserter(v2), + boost::identity()); + BOOST_TEST(v2 == v1); +} + +int main() +{ + simple_test(); + algorithm_test(); + return boost::report_errors(); +}