From 3d3560c12d8299d0ed11a90dc505e3002c4d9e3c Mon Sep 17 00:00:00 2001 From: Kohei Takahashi Date: Thu, 18 Sep 2014 16:37:28 +0900 Subject: [PATCH 1/7] Avoid 'reference to reference' error in C++03. Some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject 'reference-to-reference' in the template and typedef which described in CWG DR106 [1]. In such situations, iterator_facade rejects reference type as a value type and some special iterators will become ill-formed: the test libs/range/test/join.hpp might be descriptive. [1] http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106 Signed-off-by: Kohei Takahashi --- include/boost/iterator/is_lvalue_iterator.hpp | 3 +- .../boost/iterator/is_readable_iterator.hpp | 3 +- include/boost/iterator/iterator_facade.hpp | 11 +++- test/iterator_facade.cpp | 65 ++++++++++++++++++- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index 20c4f38..5607a0f 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -9,6 +9,7 @@ #include #include +#include #include // should be the last #includes @@ -52,7 +53,7 @@ namespace detail // convertible to Value const& struct conversion_eater { - conversion_eater(Value&); + conversion_eater(typename add_lvalue_reference::type); }; static char tester(conversion_eater, int); diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index 3f08b92..d2e5e9f 100644 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -26,7 +27,7 @@ namespace detail template struct is_readable_iterator_impl { - static char tester(Value&, int); + static char tester(typename add_lvalue_reference::type, int); static char (& tester(any_conversion_eater, ...) )[2]; template diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index c08a869..7b11d0a 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -284,7 +285,15 @@ namespace iterators { : mpl::eval_if< mpl::and_< // A proxy is only needed for readable iterators - is_convertible + is_convertible< + Reference + // Use add_lvalue_reference to form `reference to Value` due to + // some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject + // 'reference-to-reference' in the template which described in CWG + // DR106. + // http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106 + , typename add_lvalue_reference::type + > // No multipass iterator can have values that disappear // before positions can be re-visited diff --git a/test/iterator_facade.cpp b/test/iterator_facade.cpp index 9585298..9200cc1 100644 --- a/test/iterator_facade.cpp +++ b/test/iterator_facade.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -49,14 +50,14 @@ class counter_iterator struct proxy { proxy(int& x) : state(x) {} - + operator int const&() const { return state; } int& operator=(int x) { state = x; return state; } - + int& state; }; @@ -128,6 +129,61 @@ template void same_type(U const&) { BOOST_MPL_ASSERT((boost::is_same)); } +template +struct abstract_iterator + : boost::iterator_facade< + abstract_iterator + , A & + // In order to be value type as a reference, traversal category has + // to satisfy least forward traversal. + , boost::forward_traversal_tag + , A & + > +{ + abstract_iterator(I iter) : iter(iter) {} + + void increment() + { ++iter; } + + A & dereference() const + { return *iter; } + + bool equal(abstract_iterator const& y) const + { return iter == y.iter; } + + I iter; +}; + +struct base +{ + virtual void assign(const base &) = 0; + virtual bool equal(const base &) const = 0; +}; + +struct derived : base +{ + derived(int state) : state(state) { } + derived(const derived &d) : state(d.state) { } + derived(const base &b) { derived::assign(b); } + + virtual void assign(const base &b) + { + state = boost::polymorphic_cast(&b)->state; + } + + virtual bool equal(const base &b) const + { + return state == boost::polymorphic_cast(&b)->state; + } + + int state; +}; + +inline bool operator==(const base &lhs, const base &rhs) +{ + return lhs.equal(rhs); +} + int main() { { @@ -162,5 +218,10 @@ int main() BOOST_TEST(i.m_x == 2); } + { + derived d(1); + boost::readable_iterator_test(abstract_iterator(&d), derived(1)); + } + return boost::report_errors(); } From d12d60fa12ec4fc91852c2e8b5ff91c3c7d45d38 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Wed, 21 Jan 2015 16:54:54 +0000 Subject: [PATCH 2/7] Update is_lvalue_iterator.hpp In the current type_traits rewrite, type_traits headers no long implicitly include mpl ones, so mpl/bool.hpp has to be explicitly included now. --- include/boost/iterator/is_lvalue_iterator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index 5607a0f..26ee9d2 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -11,6 +11,7 @@ #include #include +#include "boost/mpl/bool.hpp" // should be the last #includes #include From 8be623d733de1e91e8b6a7d79557e6428b888daa Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Thu, 22 Jan 2015 08:48:25 +0000 Subject: [PATCH 3/7] Update is_lvalue_iterator.hpp --- include/boost/iterator/is_lvalue_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index 26ee9d2..a4c2eab 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -11,7 +11,7 @@ #include #include -#include "boost/mpl/bool.hpp" +#include // should be the last #includes #include From 53cbba6c09ba06f898c72087e3fae7b53cf4bc10 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 26 Jan 2015 00:02:36 +0300 Subject: [PATCH 4/7] Remove unused name import As Boost.Range has been updated, there is no need to import pure_traversal_tag into boost::iterators::detail. --- include/boost/iterator/iterator_categories.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index 31b2a9d..71202c9 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -168,13 +168,6 @@ struct pure_traversal_tag { }; -// This import is needed for backward compatibility with Boost.Range: -// boost/range/detail/demote_iterator_traversal_tag.hpp -// It should be removed when that header is fixed. -namespace detail { -using iterators::pure_traversal_tag; -} // namespace detail - // // Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. // From 2de2111db234be9529b4fa27592eb9e5985ae722 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Wed, 1 Apr 2015 19:00:11 -0400 Subject: [PATCH 5/7] Remove dependency on deprecated type_traits headers. --- include/boost/iterator/is_lvalue_iterator.hpp | 16 +++++++++------- include/boost/iterator/is_readable_iterator.hpp | 10 +++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index a4c2eab..24b0dab 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -14,7 +14,7 @@ #include // should be the last #includes -#include +#include #include #ifndef BOOST_NO_IS_CONVERTIBLE @@ -136,13 +136,15 @@ namespace detail {}; } // namespace detail -// Define the trait with full mpl lambda capability and various broken -// compiler workarounds -BOOST_TT_AUX_BOOL_TRAIT_DEF1( - is_lvalue_iterator,T,::boost::iterators::detail::is_readable_lvalue_iterator_impl::value) +template< typename T > struct is_lvalue_iterator +: public ::boost::integral_constant::value> +{ +}; -BOOST_TT_AUX_BOOL_TRAIT_DEF1( - is_non_const_lvalue_iterator,T,::boost::iterators::detail::is_non_const_lvalue_iterator_impl::value) +template< typename T > struct is_non_const_lvalue_iterator +: public ::boost::integral_constant::value> +{ +}; } // namespace iterators diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index d2e5e9f..01e5fa8 100644 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -8,10 +8,10 @@ #include #include -#include #include // should be the last #include +#include #include #ifndef BOOST_NO_IS_CONVERTIBLE @@ -97,10 +97,10 @@ namespace detail {}; } // namespace detail -// Define the trait with full mpl lambda capability and various broken -// compiler workarounds -BOOST_TT_AUX_BOOL_TRAIT_DEF1( - is_readable_iterator,T,::boost::iterators::detail::is_readable_iterator_impl2::value) +template< typename T > struct is_readable_iterator +: public ::boost::integral_constant::value> +{ +}; } // namespace iterators From 0dbbb61bec53dc035eb5ce37b9c9a7f2bb592a92 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Wed, 1 Apr 2015 20:02:01 -0400 Subject: [PATCH 6/7] Put back MPL auxiliary lambda support. --- include/boost/iterator/is_lvalue_iterator.hpp | 5 +++++ include/boost/iterator/is_readable_iterator.hpp | 3 +++ 2 files changed, 8 insertions(+) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index 24b0dab..cd866d6 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -12,6 +12,7 @@ #include #include #include +#include // should be the last #includes #include @@ -139,11 +140,15 @@ namespace detail template< typename T > struct is_lvalue_iterator : public ::boost::integral_constant::value> { +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_lvalue_iterator,(T)) }; template< typename T > struct is_non_const_lvalue_iterator : public ::boost::integral_constant::value> { +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_non_const_lvalue_iterator,(T)) }; } // namespace iterators diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index 01e5fa8..5bc2339 100644 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -5,6 +5,7 @@ # define IS_READABLE_ITERATOR_DWA2003112_HPP #include +#include #include #include @@ -100,6 +101,8 @@ namespace detail template< typename T > struct is_readable_iterator : public ::boost::integral_constant::value> { +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_readable_iterator,(T)) }; } // namespace iterators From b62dc6ba9df905108dbc1e12cc2d4ea6248f550d Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Fri, 22 May 2015 00:54:44 -0400 Subject: [PATCH 7/7] Remove unneeded header file for undefines. --- include/boost/iterator/is_lvalue_iterator.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index cd866d6..e821da9 100644 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -161,6 +161,5 @@ using iterators::is_non_const_lvalue_iterator; #endif #include -#include #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP