incubator-stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Travis Vitek" <Travis.Vi...@roguewave.com>
Subject RE: svn commit: r635439 - /stdcxx/trunk/include/string.cc
Date Mon, 10 Mar 2008 18:35:53 GMT
 
>Author: faridz
>Date: Sun Mar  9 22:52:37 2008
>New Revision: 635439
>
>URL: http://svn.apache.org/viewvc?rev=635439&view=rev
>Log:
>2008-03-10 Farid Zaripov <farid_zaripov@epam.com>
>
>	* include/string.cc (__replace_aux): Use static_cast<>()
>	instead of reinterpret_cast<>() to prevent compile error
>	when _InputIter::operator*() returns rvalue.
>
>Modified:
>    stdcxx/trunk/include/string.cc
>
>Modified: stdcxx/trunk/include/string.cc
>URL: 
>http://svn.apache.org/viewvc/stdcxx/trunk/include/string.cc?rev
=635439&r1=635438&r2=635439&view=diff
>===============================================================
>===============
>--- stdcxx/trunk/include/string.cc (original)
>+++ stdcxx/trunk/include/string.cc Sun Mar  9 22:52:37 2008
>@@ -652,7 +652,7 @@
> 
>             if (__n2) {
>                 const const_pointer __ptr =
>-                    &_RWSTD_REINTERPRET_CAST 
>(const_reference, *__first2);
>+                    &_RWSTD_STATIC_CAST (const_reference, *__first2);
> 
>                 if (__s.data () <= __ptr && __s.data () + 
>__ssize > __ptr) {
>                     const _RWSTD_SIZE_T __tmp_size = __n2 * 
>sizeof (value_type);
>
>
>

Farid,

Is this actually safe, and does it actually do what you want? If
_InputIter::operator* returns a rvalue and you static_cast that to a
const_reference, you will get the address of the temporary. That address
can't reliably be used to to test that `__first2' is inside `__s' or
not, so the bug that you are trying to eliminate here will still exist
for iterators of this type. Here is a complete testcase.



    template <class _TypeT>
    struct dumb_forward_iterator
    {
        dumb_forward_iterator (_TypeT* p) : ptr (p) { }

        // generated...
        //dumb_forward_iterator (const dumb_forward_iterator& other);
        //
        // generated...
        //dumb_forward_iterator&
        //operator= (const dumb_forward_iterator& other);

        _TypeT operator* ()       { return *ptr; }
        _TypeT operator* () const { return *ptr; }

              _TypeT* operator-> ()       { return ptr; }
        const _TypeT* operator-> () const { return ptr; }

        dumb_forward_iterator& operator++ ()
        { ++ptr; return *this; }

        dumb_forward_iterator operator++ (int)
        {
            dumb_forward_iterator tmp (*this);
            ++ptr;
            return tmp;
        }

        _TypeT* ptr;
    };

    template <class _TypeT>
    bool operator== (const dumb_forward_iterator<_TypeT>& lhs,
                     const dumb_forward_iterator<_TypeT>& rhs)
    {
        return lhs.ptr == rhs.ptr;
    }

    template <class _TypeT>
    bool operator!= (const dumb_forward_iterator<_TypeT>& lhs,
                     const dumb_forward_iterator<_TypeT>& rhs)
    {
        return lhs.ptr != rhs.ptr;
    }


    #include <stdlib.h>
    #include <stdio.h>

    template <class _CharT>
    struct string
    {
        typedef _CharT value_type;

        typedef _CharT* iterator;
        typedef const _CharT* const_iterator;

        typedef _CharT& reference;
        typedef const _CharT& const_reference;

        typedef _CharT* pointer;
        typedef const _CharT* const_pointer;

        string (const _CharT* s)
        {
            int n = 0;
            while (s [n])
                ++n;

            buf  = (_CharT*)malloc (n + 1);
            size = n;

            for (int m = 0; m < n; ++m)
                buf [m] = s [m];
        }

        ~string ()
        {
            free (buf);
        }

        iterator begin ()
        {
            return buf;
        }

        iterator end ()
        {
            return buf + size;
        }

        _CharT* buf;
        int size;
    };

    template <class _CharT, class _InputIter>
    void
    __replace_aux (string<_CharT>& __s, typename
string<_CharT>::iterator __first1,
                   typename string<_CharT>::iterator __last1,
                   _InputIter __first2, _InputIter __last2)
    {
        const string<_CharT>::const_pointer __ptr =
            &static_cast<string<_CharT>::const_reference>(*__first2);

        if (__s.buf <= __ptr && __ptr < __s.buf + __s.size)
            printf ("__first2 is inside __s\n");
        else
            printf ("__first2 is *not* inside __s\n");
    }

    int main ()
    {
        string<char> s ("abc");

        dumb_forward_iterator<string<char>::value_type> dbeg (s.begin
());
        dumb_forward_iterator<string<char>::value_type> dend (s.end
());

        __replace_aux (s, s.begin (), s.end (), dbeg, dend);

        return 0;
    }

If _InputIter is a pointer type, you should not need a cast at all, and
if it is a class type, you _should_ be able to use the result of
operator->(), but that isn't really safe because it could return a proxy
for the actual pointer. I think you could use SFINAE and traits to
detect that the return type of operator->() is a pointer type if we
really wanted to, and then just make a copy if it isn't.

Travis






Mime
View raw message