Boost logo

Boost Users :

Subject: [Boost-users] [iterator] unrelated type problem with iterator_facade arrow operator
From: Michael Fawcett (michael.fawcett_at_[hidden])
Date: 2009-03-23 12:43:34


Michael Fawcett <michael.fawcett <at> gmail.com> writes:
>
> Can someone confirm if the attached code doesn't compile intentionally
> or if this is a bug? I'm sorry for not posting a minimal example but
> I couldn't figure out how to reduce the problem.

Ping with complete code this time. Hopefully that will help with a response. I
also added my work-around to the code.

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/utility/enable_if.hpp>

#include <atlbase.h>

#include <cassert>
#include <vector>

//#define POSSIBLE_FIX

#ifdef POSSIBLE_FIX
// Not sure if this is a bug in Boost (doubt it) or just necessary
// since CComBSTR overloads the address-of operator to return a
// type (BSTR) that is not implicitly convertible to CComBSTR *.
namespace boost {
namespace detail {

        template <typename Reference, typename Pointer>
        struct operator_arrow_result<ATL::CComBSTR, Reference, Pointer>
        {
                typedef typename mpl::if_<
                        is_reference<Reference>
                        , Pointer
                        , operator_arrow_proxy<ATL::CComBSTR>
>::type type;

                static type make(Reference x)
                {
                        return implicit_cast<type>(boost::addressof(x));
                }
        };
}
}
#endif

namespace detail {

template <typename T>
struct CAdapt_pointee { };

template <typename T>
struct CAdapt_pointee<ATL::CAdapt<T> > {
        typedef T type;
};

template <typename Iterator, typename T>
struct m_T_type_add_const_conditionally {
        typedef typename CAdapt_pointee<typename
boost::iterator_value<Iterator>::type>::type type;
};

template <typename Iterator, typename T>
struct m_T_type_add_const_conditionally<Iterator, const T *> {
        typedef typename boost::add_const<typename CAdapt_pointee<typename
boost::iterator_value<Iterator>::type>::type>::type type;
};

template <typename T>
struct m_T_type {
        typedef typename m_T_type_add_const_conditionally<T, typename
boost::iterator_pointer<T>::type>::type type;
};
}

template <class Iterator>
class CAdapt_iterator : public
        boost::iterator_adaptor
        <
                CAdapt_iterator<Iterator>,
                Iterator,
                typename detail::m_T_type<Iterator>::type,
                typename boost::iterator_category<Iterator>::type,
                typename detail::m_T_type<Iterator>::type &
> {
private:
        struct enabler { };
        typedef typename detail::m_T_type<Iterator>::type &reference_type;

public:
        CAdapt_iterator() { }
        CAdapt_iterator(Iterator p) : CAdapt_iterator::iterator_adaptor_(p) { }

        template <class OtherValue>
        CAdapt_iterator(const CAdapt_iterator<OtherValue> &other,
                typename boost::enable_if<boost::is_convertible<OtherValue *, Iterator *>,
enabler>::type = enabler())
        : CAdapt_iterator::iterator_adaptor_(other.base()) { }

private:
        friend class boost::iterator_core_access;

        reference_type dereference() const { return this->base()->m_T; }
};

template <typename Iterator>
CAdapt_iterator<Iterator> make_CAdapt_iterator(Iterator i) {
        return CAdapt_iterator<Iterator>(i);
}

int main() {
        std::vector<CAdapt<CComBSTR> > buffer(1, CComBSTR(L"Hello, World!"));
        assert(*make_CAdapt_iterator(buffer.begin()) == L"Hello, World!");

        // This line causes the compile-error if POSSIBLE_FIX is not defined
        make_CAdapt_iterator(buffer.begin())->Empty();
        assert(buffer[0].m_T.Length() == 0);
}

--Michael Fawcett


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net