Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/reference/adaptors.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ rng | boost::adaptors::adaptor_generator
[include adaptors/map_keys.qbk]
[include adaptors/map_values.qbk]
[include adaptors/ref_unwrapped.qbk]
[include adaptors/addressed.qbk]
[include adaptors/replaced.qbk]
[include adaptors/replaced_if.qbk]
[include adaptors/reversed.qbk]
Expand Down
40 changes: 40 additions & 0 deletions doc/reference/adaptors/addressed.qbk
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[/
Copyright 2022 Denis Mikhailov
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:addressed addressed]

[table
[[Syntax] [Code]]
[[Pipe] [`rng | boost::adaptors::addressed`]]
[[Function] [`boost::adaptors::addressof(rng)`]]
]

This adaptor produces a range than applies `boost::addressof` on all values in
the range.

* [*Precondition:] For any `value_type` of the range.
* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `boost::addressof(y)` where `y` is the corresponding element in the original range.
* [*Range Category:] __single_pass_range__
* [*Range Return Type:] `boost::addressof_range<decltype(rng)>`
* [*Returned Range Category:] The range category of `rng`.

[section:addressed_example addressed example]
[import ../../../test/adaptor_test/addressed_example.cpp]
[addressed_example]
[endsect]

This would produce the output:
``
Element = 10 Address = 0x1b83310
Element = 20 Address = 0x1b83314
Element = 30 Address = 0x1b83318
Element = 40 Address = 0x1b8331c
Element = 50 Address = 0x1b83320
Element = 60 Address = 0x1b83324
Element = 70 Address = 0x1b83328
Element = 80 Address = 0x1b8332c
Element = 90 Address = 0x1b83330
``
[endsect]
126 changes: 126 additions & 0 deletions include/boost/range/adaptor/addressed.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Boost.Range library
//
// Copyright Denis Mikhailov 2022.
// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_ADAPTOR_ADDRESSED_HPP
#define BOOST_RANGE_ADAPTOR_ADDRESSED_HPP

#include <boost/range/adaptor/transformed.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/iterator.hpp>

#include <boost/core/addressof.hpp>

#include <utility>

namespace boost
{
namespace range_detail
{
struct addressof_forwarder {};

template<typename Reference>
struct addressof_value
{
BOOST_STATIC_ASSERT(boost::is_reference<Reference>::value);
typedef typename boost::remove_reference<Reference>::type* result_type;
typedef Reference argument_type;

result_type operator()(argument_type x) const
{
return boost::addressof(x);
}
};

template< typename R >
struct addressof_range :
boost::iterator_range<
boost::transform_iterator<
addressof_value<typename boost::range_reference<R>::type>,
typename boost::range_iterator<R>::type> >
{
private:
typedef typename boost::range_reference<R>::type reference_type;
typedef typename boost::range_iterator<R>::type iterator_base;
typedef addressof_value<reference_type> Fn;
typedef boost::transform_iterator<Fn, iterator_base> iterator;
typedef boost::iterator_range<iterator> base;

public:
addressof_range(R& r)
: base(iterator(boost::begin(r), Fn()),
iterator(boost::end(r), Fn()))
{ }
};

template< class SinglePassRange >
inline addressof_range<SinglePassRange>
operator|( SinglePassRange& r, addressof_forwarder )
{
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<SinglePassRange>));

return addressof_range<SinglePassRange>( r );
}

template< class SinglePassRange >
inline addressof_range<const SinglePassRange>
operator|( const SinglePassRange& r, addressof_forwarder )
{
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<SinglePassRange>));

return addressof_range<const SinglePassRange>( r );
}

}

using range_detail::addressof_range;

namespace adaptors
{
namespace
{
const range_detail::addressof_forwarder addressed =
range_detail::addressof_forwarder();
}

template<class SinglePassRange>
inline addressof_range<SinglePassRange>
addressof(SinglePassRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<SinglePassRange>));

return addressof_range<SinglePassRange>( rng );
}

template<class SinglePassRange>
inline addressof_range<const SinglePassRange>
addressof(const SinglePassRange& rng)
{
BOOST_RANGE_CONCEPT_ASSERT((
SinglePassRangeConcept<SinglePassRange>));

return addressof_range<const SinglePassRange>( rng );
}
} // 'adaptors'

}

#endif
1 change: 1 addition & 0 deletions include/boost/range/adaptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#ifndef BOOST_RANGE_ADAPTORS_HPP
#define BOOST_RANGE_ADAPTORS_HPP

#include <boost/range/adaptor/addressed.hpp>
#include <boost/range/adaptor/adjacent_filtered.hpp>
#include <boost/range/adaptor/copied.hpp>
#include <boost/range/adaptor/filtered.hpp>
Expand Down
2 changes: 2 additions & 0 deletions test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ test-suite range :
[ range-test adaptor_test/map ]
[ range-test adaptor_test/ref_unwrapped ]
[ range-test adaptor_test/ref_unwrapped_example ]
[ range-test adaptor_test/addressed ]
[ range-test adaptor_test/addressed_example ]
[ range-test adaptor_test/replaced ]
[ range-test adaptor_test/replaced_if ]
[ range-test adaptor_test/reversed ]
Expand Down
60 changes: 60 additions & 0 deletions test/adaptor_test/addressed.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Boost.Range library
//
// Copyright Denis Mikhailov 2022.
// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

#include <boost/range/adaptor/addressed.hpp>

#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>

#include <boost/range.hpp>
#include <boost/assign.hpp>

#include <vector>

namespace boost
{
namespace
{
void simple_test()
{
using namespace boost::assign;
using namespace boost::adaptors;
std::vector<int> a = list_of(1)(2)(3);
BOOST_CHECK(boost::copy_range<std::vector<int*> >(a | addressed)
== list_of(&a[0])(&a[1])(&a[2]));
BOOST_CHECK(boost::copy_range<std::vector<int*> >(addressof(a))
== list_of(&a[0])(&a[1])(&a[2]));
}

void simple_const_test()
{
using namespace boost::assign;
using namespace boost::adaptors;
const std::vector<int> a = list_of(1)(2)(3);
BOOST_CHECK(boost::copy_range<std::vector<const int*> >(a | addressed)
== list_of(&a[0])(&a[1])(&a[2]));
BOOST_CHECK(boost::copy_range<std::vector<const int*> >(addressof(a))
== list_of(&a[0])(&a[1])(&a[2]));
}
}
}

boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.addressed" );

test->add(BOOST_TEST_CASE(&boost::simple_test));
test->add(BOOST_TEST_CASE(&boost::simple_const_test));

return test;
}
104 changes: 104 additions & 0 deletions test/adaptor_test/addressed_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Boost.Range library
//
// Copyright Denis Mikhailov 2022.
// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

//[addressed_example

//<-
#include <boost/config.hpp>
//->

#include <boost/range/adaptor/addressed.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <vector>

//<-
#include <boost/core/addressof.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>

namespace
{

template<class Iterator1, class Iterator2>
void check_element_and_address(
Iterator1 test_first,
Iterator1 test_last,
Iterator2 reference_first,
Iterator2 reference_last)
{
BOOST_CHECK_EQUAL( std::distance(test_first, test_last),
std::distance(reference_first, reference_last) );

Iterator1 test_it = test_first;
Iterator2 reference_it = reference_first;
for (; test_it != test_last; ++test_it, ++reference_it)
{
BOOST_CHECK_EQUAL(**test_it, *reference_it);
BOOST_CHECK_EQUAL(*test_it, boost::addressof(*reference_it));
}
}

template<class SinglePassRange1, class SinglePassRange2>
void check_element_and_address(
const SinglePassRange1& test_rng,
const SinglePassRange2& reference_rng)
{
check_element_and_address(
boost::begin(test_rng), boost::end(test_rng),
boost::begin(reference_rng), boost::end(reference_rng));
}
//->

//<-
void addressed_example_test()
//->
//=int main(int argc, const char* argv[])
{
using namespace boost::assign;
using namespace boost::adaptors;

std::vector<int> input;
input += 10,20,30,40,50,60,70,80,90;

//<-
#ifndef BOOST_NO_CXX11_RANGE_BASED_FOR
//->
for (const auto& address : input | addressed)
{
std::cout << "Element = " << *address
<< " Address = " << address
<< std::endl;
}
//<-
#endif // C++11 has range for loop
//->

//= return 0;
//=}
//]
check_element_and_address(
input | addressed,
input);
}
}

boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.addressed_example" );

test->add( BOOST_TEST_CASE( &addressed_example_test ) );

return test;
}