mirror of
https://github.com/boostorg/iterator.git
synced 2025-05-12 05:51:37 +00:00
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 <flast@flast.jp>
This commit is contained in:
parent
adee905c51
commit
3d3560c12d
@ -9,6 +9,7 @@
|
|||||||
#include <boost/detail/workaround.hpp>
|
#include <boost/detail/workaround.hpp>
|
||||||
#include <boost/detail/iterator.hpp>
|
#include <boost/detail/iterator.hpp>
|
||||||
|
|
||||||
|
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||||
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||||
|
|
||||||
// should be the last #includes
|
// should be the last #includes
|
||||||
@ -52,7 +53,7 @@ namespace detail
|
|||||||
// convertible to Value const&
|
// convertible to Value const&
|
||||||
struct conversion_eater
|
struct conversion_eater
|
||||||
{
|
{
|
||||||
conversion_eater(Value&);
|
conversion_eater(typename add_lvalue_reference<Value>::type);
|
||||||
};
|
};
|
||||||
|
|
||||||
static char tester(conversion_eater, int);
|
static char tester(conversion_eater, int);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <boost/mpl/bool.hpp>
|
#include <boost/mpl/bool.hpp>
|
||||||
#include <boost/detail/iterator.hpp>
|
#include <boost/detail/iterator.hpp>
|
||||||
|
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/detail/bool_trait_def.hpp>
|
#include <boost/type_traits/detail/bool_trait_def.hpp>
|
||||||
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||||
@ -26,7 +27,7 @@ namespace detail
|
|||||||
template <class Value>
|
template <class Value>
|
||||||
struct is_readable_iterator_impl
|
struct is_readable_iterator_impl
|
||||||
{
|
{
|
||||||
static char tester(Value&, int);
|
static char tester(typename add_lvalue_reference<Value>::type, int);
|
||||||
static char (& tester(any_conversion_eater, ...) )[2];
|
static char (& tester(any_conversion_eater, ...) )[2];
|
||||||
|
|
||||||
template <class It>
|
template <class It>
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <boost/type_traits/is_same.hpp>
|
#include <boost/type_traits/is_same.hpp>
|
||||||
#include <boost/type_traits/add_const.hpp>
|
#include <boost/type_traits/add_const.hpp>
|
||||||
#include <boost/type_traits/add_pointer.hpp>
|
#include <boost/type_traits/add_pointer.hpp>
|
||||||
|
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||||
#include <boost/type_traits/remove_const.hpp>
|
#include <boost/type_traits/remove_const.hpp>
|
||||||
#include <boost/type_traits/remove_reference.hpp>
|
#include <boost/type_traits/remove_reference.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
@ -284,7 +285,15 @@ namespace iterators {
|
|||||||
: mpl::eval_if<
|
: mpl::eval_if<
|
||||||
mpl::and_<
|
mpl::and_<
|
||||||
// A proxy is only needed for readable iterators
|
// A proxy is only needed for readable iterators
|
||||||
is_convertible<Reference,Value const&>
|
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<Value const>::type
|
||||||
|
>
|
||||||
|
|
||||||
// No multipass iterator can have values that disappear
|
// No multipass iterator can have values that disappear
|
||||||
// before positions can be re-visited
|
// before positions can be re-visited
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <boost/iterator/new_iterator_tests.hpp>
|
#include <boost/iterator/new_iterator_tests.hpp>
|
||||||
|
|
||||||
#include <boost/call_traits.hpp>
|
#include <boost/call_traits.hpp>
|
||||||
|
#include <boost/polymorphic_cast.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
#include <boost/utility/enable_if.hpp>
|
#include <boost/utility/enable_if.hpp>
|
||||||
|
|
||||||
@ -49,14 +50,14 @@ class counter_iterator
|
|||||||
struct proxy
|
struct proxy
|
||||||
{
|
{
|
||||||
proxy(int& x) : state(x) {}
|
proxy(int& x) : state(x) {}
|
||||||
|
|
||||||
operator int const&() const
|
operator int const&() const
|
||||||
{
|
{
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int& operator=(int x) { state = x; return state; }
|
int& operator=(int x) { state = x; return state; }
|
||||||
|
|
||||||
int& state;
|
int& state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,6 +129,61 @@ template <class T, class U>
|
|||||||
void same_type(U const&)
|
void same_type(U const&)
|
||||||
{ BOOST_MPL_ASSERT((boost::is_same<T,U>)); }
|
{ BOOST_MPL_ASSERT((boost::is_same<T,U>)); }
|
||||||
|
|
||||||
|
template <class I, class A>
|
||||||
|
struct abstract_iterator
|
||||||
|
: boost::iterator_facade<
|
||||||
|
abstract_iterator<I, A>
|
||||||
|
, 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<const derived *>(&b)->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool equal(const base &b) const
|
||||||
|
{
|
||||||
|
return state == boost::polymorphic_cast<const derived *>(&b)->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int state;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const base &lhs, const base &rhs)
|
||||||
|
{
|
||||||
|
return lhs.equal(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -162,5 +218,10 @@ int main()
|
|||||||
BOOST_TEST(i.m_x == 2);
|
BOOST_TEST(i.m_x == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
derived d(1);
|
||||||
|
boost::readable_iterator_test(abstract_iterator<derived *, base>(&d), derived(1));
|
||||||
|
}
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user