mirror of
https://github.com/boostorg/iterator.git
synced 2025-05-11 05:23:52 +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/iterator.hpp>
|
||||
|
||||
#include <boost/type_traits/add_lvalue_reference.hpp>
|
||||
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||
|
||||
// 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<Value>::type);
|
||||
};
|
||||
|
||||
static char tester(conversion_eater, int);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <boost/mpl/bool.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/iterator/detail/any_conversion_eater.hpp>
|
||||
@ -26,7 +27,7 @@ namespace detail
|
||||
template <class Value>
|
||||
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];
|
||||
|
||||
template <class It>
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/add_const.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_reference.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
@ -284,7 +285,15 @@ namespace iterators {
|
||||
: mpl::eval_if<
|
||||
mpl::and_<
|
||||
// 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
|
||||
// before positions can be re-visited
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <boost/iterator/new_iterator_tests.hpp>
|
||||
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/polymorphic_cast.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
@ -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 <class T, class U>
|
||||
void same_type(U const&)
|
||||
{ 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()
|
||||
{
|
||||
{
|
||||
@ -162,5 +218,10 @@ int main()
|
||||
BOOST_TEST(i.m_x == 2);
|
||||
}
|
||||
|
||||
{
|
||||
derived d(1);
|
||||
boost::readable_iterator_test(abstract_iterator<derived *, base>(&d), derived(1));
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user