March 31, 2005
Tried using non-template overloads for the char/wchar_t. Still ICEs

#if 0
    template<typename CHAR_TYPE>
    stlsoft_ns_qual(basic_string_view)<CHAR_TYPE>
    right_view(
         CHAR_TYPE const* str
       , size_t cch
    )
    {
       typedef stlsoft_ns_qual(basic_string_view)<CHAR_TYPE> string_view_t;

       size_t size = ::stlsoft::c_str_len(str);
       return (size <= cch)
           ? string_view_t(str, cch)
           : string_view_t(str + (size - cch), cch)
           ;
    }
#else

    stlsoft_ns_qual(basic_string_view)<char> right_view(char const *str, size_t cch)
    {
       typedef stlsoft_ns_qual(basic_string_view)<char> string_view_t;

       size_t size = ::stlsoft::c_str_len(str);
       return (size <= cch)
           ? string_view_t(str, cch)
           : string_view_t(str + (size - cch), cch)
           ;
    }

    stlsoft_ns_qual(basic_string_view)<wchar_t> right_view(wchar_t const *str, size_t cch)
    {
       typedef stlsoft_ns_qual(basic_string_view)<wchar_t> string_view_t;

       size_t size = ::stlsoft::c_str_len(str);
       return (size <= cch)
           ? string_view_t(str, cch)
           : string_view_t(str + (size - cch), cch)
           ;
    }

#endif /* 0 */


March 31, 2005
"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2i0mf$258r$1@digitaldaemon.com...
> I've rewritten to try and get around VC6. But the following still ICEs
>
>    template<ss_typename_param_k T>
>    struct string_traits_
>    {
>        typedef typename T::value_type  char_type;
>        typedef typename T::size_type   size_type;
>
>        static char_type const  *get_data(T const &s)
>        {
>            return s.data();
>        }
>        static size_type        get_length(T const &s)
>        {
>            return s.size();
>        }
>    };

Do you not use your ss_typename_type_k define for char_type and size_type?

>    template<>
>    struct string_traits_<char const*>
>    {
>        typedef char            char_type;
>        typedef size_t          size_type;
>
>        static char_type const *get_data(char_type const *s)
>        {
>            return s;
>        }
>        static size_type        get_length(char_type const *s)
>        {
>            return strlen(s);
>        }
>    };
>
>    template<>
>    struct string_traits_<wchar_t const*>
>    {
>        typedef wchar_t         char_type;
>        typedef size_t          size_type;
>
>        static char_type const *get_data(char_type const *s)
>        {
>            return s;
>        }
>        static size_type        get_length(char_type const *s)
>        {
>            return wcslen(s);
>        }
>    };
>
>
>    template<ss_typename_param_k S>
>    const ::stlsoft::basic_string_view<ss_typename_type_k
> string_traits_<S>::char_type> right_view(S const &s, ss_typename_type_k
> string_traits_<S>::size_type n)
>    {
>        typedef string_traits_<S>                       traits_t;
>        typedef traits_t::char_type                     char_t;
>        typedef traits_t::size_type                     size_t;
>        typedef ::stlsoft::basic_string_view<char_t>    string_view_t;
>
>        char_t const    *data   =   traits_t::get_data(s);
>        const size_t    len     =   c_str_len(s);///*
> traits_t::get_length(s) */0;
>
>        if(n > len)
>        {
>            n = len;
>        }
>
>        return string_view_t(data + (len - n), n);
>    }

Where's the ICE happening?

Pablo


March 31, 2005
Success!!!

Please don't ask me why this works, but it does. Clean-compiles in Arturius with all the previously mentioned compilers: :-)

    template <ss_typename_param_k S>
    struct right_view_traits
    {
        typedef S                                           string_type;
        typedef ss_typename_type_k string_type::value_type  char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    template <>
    struct right_view_traits<char const *>
    {
        typedef char                                        char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    template <>
    struct right_view_traits<wchar_t const *>
    {
        typedef wchar_t                                     char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    ::stlsoft::basic_string_view<char>                  right_view(char const *s, size_t n)
    {
        const size_t    len =   ::stlsoft::c_str_len(s);

        if(n > len)
        {
            // Want more than is available, so get all, from start
            n = len;
        }
        else
        {
            // Want less than is available, so get n from end
            s += (len - n);
        }

        return ::stlsoft::basic_string_view<char>(s, n);
    }

    ::stlsoft::basic_string_view<wchar_t>               right_view(wchar_t const *s, size_t n)
    {
        const size_t    len =   ::stlsoft::c_str_len(s);

        if(n > len)
        {
            // Want more than is available, so get all, from start
            n = len;
        }
        else
        {
            // Want less than is available, so get n from end
            s += (len - n);
        }

        return ::stlsoft::basic_string_view<wchar_t>(s, n);
    }

    template <ss_typename_param_k S>
    ss_typename_type_k right_view_traits<S>::view_type  right_view(S const &s, size_t n)
    {
        typedef right_view_traits<S>    traits_t;

        const size_t    len =   ::stlsoft::c_str_len(s);
        size_t          off =   0;

        if(n > len)
        {
            // Want more than is available, so get all, from start
            n = len;
        }
        else
        {
            off = len - n;
        }

        return traits_t::view_type(s.data() + off, n);
    }


March 31, 2005
"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2i17r$25l5$1@digitaldaemon.com...
>
> "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2i0mf$258r$1@digitaldaemon.com...
>> I've rewritten to try and get around VC6. But the following still ICEs
>>
>>    template<ss_typename_param_k T>
>>    struct string_traits_
>>    {
>>        typedef typename T::value_type  char_type;
>>        typedef typename T::size_type   size_type;
>>
>>        static char_type const  *get_data(T const &s)
>>        {
>>            return s.data();
>>        }
>>        static size_type        get_length(T const &s)
>>        {
>>            return s.size();
>>        }
>>    };
>
> Do you not use your ss_typename_type_k define for char_type and size_type?
>
>>    template<>
>>    struct string_traits_<char const*>
>>    {
>>        typedef char            char_type;
>>        typedef size_t          size_type;
>>
>>        static char_type const *get_data(char_type const *s)
>>        {
>>            return s;
>>        }
>>        static size_type        get_length(char_type const *s)
>>        {
>>            return strlen(s);
>>        }
>>    };
>>
>>    template<>
>>    struct string_traits_<wchar_t const*>
>>    {
>>        typedef wchar_t         char_type;
>>        typedef size_t          size_type;
>>
>>        static char_type const *get_data(char_type const *s)
>>        {
>>            return s;
>>        }
>>        static size_type        get_length(char_type const *s)
>>        {
>>            return wcslen(s);
>>        }
>>    };
>>
>>
>>    template<ss_typename_param_k S>
>>    const ::stlsoft::basic_string_view<ss_typename_type_k string_traits_<S>::char_type> right_view(S const &s,
>> ss_typename_type_k string_traits_<S>::size_type n)
>>    {
>>        typedef string_traits_<S>                       traits_t;
>>        typedef traits_t::char_type                     char_t;
>>        typedef traits_t::size_type                     size_t;
>>        typedef ::stlsoft::basic_string_view<char_t>    string_view_t;
>>
>>        char_t const    *data   =   traits_t::get_data(s);
>>        const size_t    len     =   c_str_len(s);///* traits_t::get_length(s) */0;
>>
>>        if(n > len)
>>        {
>>            n = len;
>>        }
>>
>>        return string_view_t(data + (len - n), n);
>>    }
>
> Where's the ICE happening?

It says the source line is the end of run_test(). But that's not exactly definitive. It's an attempt to instantiate a/the template within that fn, methinks.

Anyway, 't'is now fixed. :-)



March 31, 2005
Slightly better version:

    template <ss_typename_param_k S>
    struct right_view_traits
    {
        typedef S                                           string_type;
        typedef ss_typename_type_k string_type::value_type  char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    template <>
    struct right_view_traits<char const *>
    {
        typedef char                                        char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    template <>
    struct right_view_traits<wchar_t const *>
    {
        typedef wchar_t                                     char_type;
        typedef ::stlsoft::basic_string_view<char_type>     view_type;
    };

    template <ss_typename_param_k C>
    ::stlsoft::basic_string_view<C>                     right_view_helper(C const *s, size_t n)
    {
        const size_t    len =   ::stlsoft::c_str_len(s);

        if(n > len)
        {
            // Want more than is available, so get all, from start
            n = len;
        }
        else
        {
            // Want less than is available, so get n from end
            s += (len - n);
        }

        return ::stlsoft::basic_string_view<C>(s, n);
    }

    ::stlsoft::basic_string_view<char>                  right_view(char const *s, size_t n)
    {
        return right_view_helper(s, n);
    }

    ::stlsoft::basic_string_view<wchar_t>               right_view(wchar_t const *s, size_t n)
    {
        return right_view_helper(s, n);
    }

    template <ss_typename_param_k S>
    ss_typename_type_k right_view_traits<S>::view_type  right_view(S const &s, size_t n)
    {
        typedef right_view_traits<S>    traits_t;

        const size_t    len =   ::stlsoft::c_str_len(s);
        size_t          off =   0;

        if(n > len)
        {
            // Want more than is available, so get all, from start
            n = len;
        }
        else
        {
            off = len - n;
        }

        return traits_t::view_type(s.data() + off, n);
    }



Note that I've been thinking of adding a c_str_data() shim to STLSoft for some time, partly related to string_view, and this definitely calls for it. Then the last line of the template version of right_view would be far more generally applicable.





April 01, 2005
So now all that's left of my code is but a memory... <g>
Can I take this and make left$ and mid$ or do you still have some more
tweaking to do?

"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2i257$26ag$1@digitaldaemon.com...
> Slightly better version:
>
>    template <ss_typename_param_k S>
>    struct right_view_traits
>    {
>        typedef S                                           string_type;
>        typedef ss_typename_type_k string_type::value_type  char_type;
>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>    };
>
>    template <>
>    struct right_view_traits<char const *>
>    {
>        typedef char                                        char_type;
>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>    };
>
>    template <>
>    struct right_view_traits<wchar_t const *>
>    {
>        typedef wchar_t                                     char_type;
>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>    };
>
>    template <ss_typename_param_k C>
>    ::stlsoft::basic_string_view<C>                     right_view_helper(C
> const *s, size_t n)
>    {
>        const size_t    len =   ::stlsoft::c_str_len(s);
>
>        if(n > len)
>        {
>            // Want more than is available, so get all, from start
>            n = len;
>        }
>        else
>        {
>            // Want less than is available, so get n from end
>            s += (len - n);
>        }
>
>        return ::stlsoft::basic_string_view<C>(s, n);
>    }
>
>    ::stlsoft::basic_string_view<char>                  right_view(char
> const *s, size_t n)
>    {
>        return right_view_helper(s, n);
>    }
>
>    ::stlsoft::basic_string_view<wchar_t>               right_view(wchar_t
> const *s, size_t n)
>    {
>        return right_view_helper(s, n);
>    }
>
>    template <ss_typename_param_k S>
>    ss_typename_type_k right_view_traits<S>::view_type  right_view(S const
> &s, size_t n)
>    {
>        typedef right_view_traits<S>    traits_t;
>
>        const size_t    len =   ::stlsoft::c_str_len(s);
>        size_t          off =   0;
>
>        if(n > len)
>        {
>            // Want more than is available, so get all, from start
>            n = len;
>        }
>        else
>        {
>            off = len - n;
>        }
>
>        return traits_t::view_type(s.data() + off, n);
>    }
>
>
>
> Note that I've been thinking of adding a c_str_data() shim to STLSoft for some time, partly related to string_view, and this definitely calls for it. Then the last line of the template version of right_view would be far more generally applicable.


April 01, 2005
"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2i38a$279u$1@digitaldaemon.com...
> So now all that's left of my code is but a memory... <g>

Hope not. I tried to stick close to it, but VC6 is a harsh mistress. ;)

> Can I take this and make left$ and mid$ or do you still have some more tweaking to do?

Nope. It's all yours. (I've sent you an email discussing various things, so I'll let you read that and get back to me at your leisure.)

Thanks for the interest, and effort in exercising string_view. (Note: there's a slight mod that you'll need *now*; see attached)

Cheers

Matthew


>
> "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2i257$26ag$1@digitaldaemon.com...
>> Slightly better version:
>>
>>    template <ss_typename_param_k S>
>>    struct right_view_traits
>>    {
>>        typedef S                                           string_type;
>>        typedef ss_typename_type_k string_type::value_type  char_type;
>>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>>    };
>>
>>    template <>
>>    struct right_view_traits<char const *>
>>    {
>>        typedef char                                        char_type;
>>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>>    };
>>
>>    template <>
>>    struct right_view_traits<wchar_t const *>
>>    {
>>        typedef wchar_t                                     char_type;
>>        typedef ::stlsoft::basic_string_view<char_type>     view_type;
>>    };
>>
>>    template <ss_typename_param_k C>
>>    ::stlsoft::basic_string_view<C>                     right_view_helper(C
>> const *s, size_t n)
>>    {
>>        const size_t    len =   ::stlsoft::c_str_len(s);
>>
>>        if(n > len)
>>        {
>>            // Want more than is available, so get all, from start
>>            n = len;
>>        }
>>        else
>>        {
>>            // Want less than is available, so get n from end
>>            s += (len - n);
>>        }
>>
>>        return ::stlsoft::basic_string_view<C>(s, n);
>>    }
>>
>>    ::stlsoft::basic_string_view<char>                  right_view(char
>> const *s, size_t n)
>>    {
>>        return right_view_helper(s, n);
>>    }
>>
>>    ::stlsoft::basic_string_view<wchar_t>               right_view(wchar_t
>> const *s, size_t n)
>>    {
>>        return right_view_helper(s, n);
>>    }
>>
>>    template <ss_typename_param_k S>
>>    ss_typename_type_k right_view_traits<S>::view_type  right_view(S const
>> &s, size_t n)
>>    {
>>        typedef right_view_traits<S>    traits_t;
>>
>>        const size_t    len =   ::stlsoft::c_str_len(s);
>>        size_t          off =   0;
>>
>>        if(n > len)
>>        {
>>            // Want more than is available, so get all, from start
>>            n = len;
>>        }
>>        else
>>        {
>>            off = len - n;
>>        }
>>
>>        return traits_t::view_type(s.data() + off, n);
>>    }
>>
>>
>>
>> Note that I've been thinking of adding a c_str_data() shim to STLSoft for some time, partly related to string_view, and this definitely calls for it. Then the last line of the template version of right_view would be far more generally applicable.
>
> 



April 01, 2005
"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d2gc12$bv9$1@digitaldaemon.com...
>
>> 1) I think the (rhs, pos, cch) constructor, is missing an assert for (pos + cch < rhs.length), pos is being checked but cch is taken literally with no checks
>
> I think I thought about this, and considered that the user might expect to be able to 'know' more about the real extent of available string than the rhs string_view instance.

Interesting point, this thought never crossed my mind...

> I'm still not 100% about it, so I'd be interested in hearing opinions on this from others.

I guess you could come up with a scenario in which you'd need a longer view than you have and know you can get it but... I'd think the only way to be sure there's more info available than what your current view knows there is, would be to know the source string for that view, in which case, wouldn't it be more "proper" to construct the new view from the original source rather than over-reading from the short view?

If I had to cast a vote, I'd say the length should be checked...

>> 2) The (char const* s, cch) constructor is missing the check for cch's validity also
>
> Definitely not in this case. <g>
>
> One important point of string_view is that it can be applied to any sequence of bytes, whether or not they're null-terminated. Also, string_view, in common with std::basic_string (and BSTR, and many other string types) may contain embedded NUL characters. Given that, how would we 'check' cch? :-)

No argument here...

>> 3) Doesn't m_base have to be pointed to m_cstr if m_cstr is allocated (when using c_str()) ?
>
> I thought it did. :$ Let me check ...
>
> ... ah, now I remember: I reasoned that users would want to be able to depend on data() and the iterators pointing into the original memory. Now that I'm reminded of that, I think it's definitely a powerful argument.

Again, no argument...

>> On "standard" issues (and please correct me since I'm likely be outdated
>> on this):
>> a) Can you can construct using the (char const* s[,cch]) versions from
>> pointers returned by c_str()? Aren't these pointers NOT guaranteed to be
>> valid after the function call?
>
> I don't follow. Can you rephrase? (and please stipulate explicitly which class you're meaning on both lhs and rhs of such interactions.)

Just reread my most, sounds weird...
I meant, that you couldn't construct from a c_str() returned pointer, since
the data pointed to could be easily invalidated as you stated below.

>> b) How would you construct a string_view from an std::string if:
>>    - iterators aren't necessarily pointers (so it can't be done through
>> begin(), end())
>>    - string memory isn't guaranteed to be contiguous (as it was pointed
>> out some time ago, but I can't find the post) ? (so it can't be done
>> either with &str[pos], &str[pos + cch])
>
> Doing it is simple:
>
>    std::basic_string<char> ss("Pablo's help is highly prized");
>    string_view<char>        sv(ss.data(), ss.length());
>
> But you're correct in suggesting that it's not theoretically valid to do so. But (I think) you're missing a more fundamental point.
>
> data() is guaranteed to return a contiguous array of characters whose first size() elements are identical to those in the actual storage (if different). The returned pointer is invalidated by a host of different operations on std::basic_string - including c_str()! - which would invalidate the pointer that the string_view instance is holding onto.

Ok, you got me here, I wasn't even aware of data()'s existance let alone requirements...

> But, and this is where this bad news is actually not that bad, the exact same could be said if a string-view class held onto iterators. Anything that invalidates iterators will invalidate the pointer returned by data(), after all. <g>
>
> So, bizarrely as it seems, the issue is moot. :-)

Agreed.

> (BTW: This is all good stuff for doing in the documentation. If only someone was motivated to help me out on the docs .... <G>)

In due time...

>> I assume it was considered storing a pair of iterators rather than a base and length as a possibility, what were the cons for that approach?
>
> Theoretically, string_view is _only_ for use with *arrays of characters*. The fact that a standards compliant string class (or indeed any other string class) may store non-continguously, means that iterators may not be used.
>
> Practically speaking, I've found that it's more convenient and more efficient to represent strings as len+ptr rather than two bounding ptrs. (And this will be reflected in the forthcoming rewrite of recls: recls2)

Interesting... could you give a brief insight as to why this is so?

>> BTW, saw myself in string_view's header, thanks!
>
> You're entirely welcome. :-)
>
> I'm a strong believer in people's help being recognised and valued.

Well, thanks again...

> Cheers
>
> Matthew

Pablo


April 04, 2005
"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2kkpd$1q6i$1@digitaldaemon.com...
>
> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d2gc12$bv9$1@digitaldaemon.com...
>>
>>> 1) I think the (rhs, pos, cch) constructor, is missing an assert for (pos + cch < rhs.length), pos is being checked but cch is taken literally with no checks
>>
>> I think I thought about this, and considered that the user might expect to be able to 'know' more about the real extent of available string than the rhs string_view instance.
>
> Interesting point, this thought never crossed my mind...
>
>> I'm still not 100% about it, so I'd be interested in hearing opinions on this from others.
>
> I guess you could come up with a scenario in which you'd need a longer view than you have and know you can get it but... I'd think the only way to be sure there's more info available than what your current view knows there is, would be to know the source string for that view, in which case, wouldn't it be more "proper" to construct the new view from the original source rather than over-reading from the short view?
>
> If I had to cast a vote, I'd say the length should be checked...
>
>>> 2) The (char const* s, cch) constructor is missing the check for cch's validity also
>>
>> Definitely not in this case. <g>
>>
>> One important point of string_view is that it can be applied to any sequence of bytes, whether or not they're null-terminated. Also, string_view, in common with std::basic_string (and BSTR, and many other string types) may contain embedded NUL characters. Given that, how would we 'check' cch? :-)
>
> No argument here...
>
>>> 3) Doesn't m_base have to be pointed to m_cstr if m_cstr is allocated (when using c_str()) ?
>>
>> I thought it did. :$ Let me check ...
>>
>> ... ah, now I remember: I reasoned that users would want to be able to depend on data() and the iterators pointing into the original memory. Now that I'm reminded of that, I think it's definitely a powerful argument.
>
> Again, no argument...
>
>>> On "standard" issues (and please correct me since I'm likely be outdated on this):
>>> a) Can you can construct using the (char const* s[,cch]) versions from pointers returned by c_str()? Aren't these
>>> pointers NOT guaranteed to be valid after the function call?
>>
>> I don't follow. Can you rephrase? (and please stipulate explicitly which class you're meaning on both lhs and rhs of such interactions.)
>
> Just reread my most, sounds weird...
> I meant, that you couldn't construct from a c_str() returned pointer, since the data pointed to could be easily
> invalidated as you stated below.
>
>>> b) How would you construct a string_view from an std::string if:
>>>    - iterators aren't necessarily pointers (so it can't be done through begin(), end())
>>>    - string memory isn't guaranteed to be contiguous (as it was pointed out some time ago, but I can't find the
>>> post) ? (so it can't be done either with &str[pos], &str[pos + cch])
>>
>> Doing it is simple:
>>
>>    std::basic_string<char> ss("Pablo's help is highly prized");
>>    string_view<char>        sv(ss.data(), ss.length());
>>
>> But you're correct in suggesting that it's not theoretically valid to do so. But (I think) you're missing a more fundamental point.
>>
>> data() is guaranteed to return a contiguous array of characters whose first size() elements are identical to those in the actual storage (if different). The returned pointer is invalidated by a host of different operations on std::basic_string - including c_str()! - which would invalidate the pointer that the string_view instance is holding onto.
>
> Ok, you got me here, I wasn't even aware of data()'s existance let alone requirements...
>
>> But, and this is where this bad news is actually not that bad, the exact same could be said if a string-view class held onto iterators. Anything that invalidates iterators will invalidate the pointer returned by data(), after all. <g>
>>
>> So, bizarrely as it seems, the issue is moot. :-)
>
> Agreed.

Cool. Sounds like our reasoning tallies, which is a relief. :-)

>> (BTW: This is all good stuff for doing in the documentation. If only someone was motivated to help me out on the docs .... <G>)
>
> In due time...

Just yanking ya. ;)

>>> I assume it was considered storing a pair of iterators rather than a base and length as a possibility, what were the cons for that approach?
>>
>> Theoretically, string_view is _only_ for use with *arrays of characters*. The fact that a standards compliant string class (or indeed any other string class) may store non-continguously, means that iterators may not be used.
>>
>> Practically speaking, I've found that it's more convenient and more efficient to represent strings as len+ptr rather than two bounding ptrs. (And this will be reflected in the forthcoming rewrite of recls: recls2)
>
> Interesting... could you give a brief insight as to why this is so?

Well, I find that I want to know the length more frequently that I want to have the (one of the) end pointer. Given that, it's less efficient to know the end than the length.



1 2
Next ›   Last »