Jump to page: 1 2
Thread overview
string_view in 1.8.3b4
Mar 31, 2005
Pablo Aguilar
Mar 31, 2005
Matthew
Mar 31, 2005
Pablo Aguilar
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Apr 01, 2005
Pablo Aguilar
Apr 04, 2005
Matthew
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Mar 31, 2005
Pablo Aguilar
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Mar 31, 2005
Pablo Aguilar
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Mar 31, 2005
Matthew
Apr 01, 2005
Pablo Aguilar
Apr 01, 2005
Matthew
March 31, 2005
I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a few comments after looking at the source...

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
2) The (char const* s, cch) constructor is missing the check for cch's
validity also
3) Doesn't m_base have to be pointed to m_cstr if m_cstr is allocated (when
using c_str()) ?

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?
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])

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?

BTW, saw myself in string_view's header, thanks!


Pablo


March 31, 2005
"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a few comments after looking at the source...

Cool. Did you figure it out? It might be a nice addition ...

> 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.

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

> 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? :-)

> 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.

> 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.)

> 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.

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. :-)

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

> 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)

> 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.

Cheers

Matthew


March 31, 2005
"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d2gc12$bv9$1@digitaldaemon.com...
>
> "Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>>I was looking at string_view to figure out how to implement BASIC-style
>>left$, right$ and mid$ functions here's a few
>>comments after looking at the source...
>
> Cool. Did you figure it out? It might be a nice addition ...

I'll reply to the whole message in a while... for now, would you mind looking at the following, it compiles fine under VC71, but either complains about "typename" being used outsie a template or ICEs on me with VC6.5

<code>
template<typename string_type>
stlsoft_ns_qual(basic_string_view)<typename string_type::value_type>
right_view(
      string_type const& str
    , typename string_type::size_type cch
)
{
    typedef stlsoft_ns_qual(basic_string_view)<typename
string_type::value_type> string_view; // <<< complains/crashes here
    // This assumes that string types below have contiguous memory storage
    typename string_type::size_type size = str.size();

    // We know we're not modifying the string
    // so the const_cast is ok, we need it to
    // get the reference version of operator[]
    // otherwise we get an rvalue return type
    string_type& ncstr = *const_cast<string_type*>(&str);
    return (size <= cch)
        ? string_view(&ncstr[0], size)
        : string_view(&ncstr[size - cch], cch)
        ;
}

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;
    size_t size = c_str_len(str);
    return (size <= cch)
        ? string_view(str, cch)
        : string_view(str + (size - cch), cch)
        ;
}
</code>

Once this works, left_view and mid_view should be trivial to implement...
Maybe taking the address of characters in certain positions should be
replaced by using a string traits class.
Attached is the test program I'm using...

Thanks for your help...

Pablo



March 31, 2005
I need softsteel/string_algo.hpp

Can you post / email it to me?

"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2hslp$21mv$1@digitaldaemon.com...
>
> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d2gc12$bv9$1@digitaldaemon.com...
>>
>> "Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>>>I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a few comments after looking at the source...
>>
>> Cool. Did you figure it out? It might be a nice addition ...
>
> I'll reply to the whole message in a while... for now, would you mind looking at the following, it compiles fine under VC71, but either complains about "typename" being used outsie a template or ICEs on me with VC6.5
>
> <code>
> template<typename string_type>
> stlsoft_ns_qual(basic_string_view)<typename string_type::value_type>
> right_view(
>      string_type const& str
>    , typename string_type::size_type cch
> )
> {
>    typedef stlsoft_ns_qual(basic_string_view)<typename string_type::value_type> string_view; // <<< complains/crashes
> here
>    // This assumes that string types below have contiguous memory storage
>    typename string_type::size_type size = str.size();
>
>    // We know we're not modifying the string
>    // so the const_cast is ok, we need it to
>    // get the reference version of operator[]
>    // otherwise we get an rvalue return type
>    string_type& ncstr = *const_cast<string_type*>(&str);
>    return (size <= cch)
>        ? string_view(&ncstr[0], size)
>        : string_view(&ncstr[size - cch], cch)
>        ;
> }
>
> 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;
>    size_t size = c_str_len(str);
>    return (size <= cch)
>        ? string_view(str, cch)
>        : string_view(str + (size - cch), cch)
>        ;
> }
> </code>
>
> Once this works, left_view and mid_view should be trivial to implement...
> Maybe taking the address of characters in certain positions should be replaced by using a string traits class.
> Attached is the test program I'm using...
>
> Thanks for your help...
>
> Pablo
>
>
> 


March 31, 2005
Doh! Belay that order. :$

"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2ht4g$226m$1@digitaldaemon.com...
>I need softsteel/string_algo.hpp
>
> Can you post / email it to me?
>
> "Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2hslp$21mv$1@digitaldaemon.com...
>>
>> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d2gc12$bv9$1@digitaldaemon.com...
>>>
>>> "Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>>>>I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a
>>>>few
>>>>comments after looking at the source...
>>>
>>> Cool. Did you figure it out? It might be a nice addition ...
>>
>> I'll reply to the whole message in a while... for now, would you mind looking at the following, it compiles fine under VC71, but either complains about "typename" being used outsie a template or ICEs on me with VC6.5
>>
>> <code>
>> template<typename string_type>
>> stlsoft_ns_qual(basic_string_view)<typename string_type::value_type>
>> right_view(
>>      string_type const& str
>>    , typename string_type::size_type cch
>> )
>> {
>>    typedef stlsoft_ns_qual(basic_string_view)<typename string_type::value_type> string_view; // <<< complains/crashes
>> here
>>    // This assumes that string types below have contiguous memory storage
>>    typename string_type::size_type size = str.size();
>>
>>    // We know we're not modifying the string
>>    // so the const_cast is ok, we need it to
>>    // get the reference version of operator[]
>>    // otherwise we get an rvalue return type
>>    string_type& ncstr = *const_cast<string_type*>(&str);
>>    return (size <= cch)
>>        ? string_view(&ncstr[0], size)
>>        : string_view(&ncstr[size - cch], cch)
>>        ;
>> }
>>
>> 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;
>>    size_t size = c_str_len(str);
>>    return (size <= cch)
>>        ? string_view(str, cch)
>>        : string_view(str + (size - cch), cch)
>>        ;
>> }
>> </code>
>>
>> Once this works, left_view and mid_view should be trivial to implement...
>> Maybe taking the address of characters in certain positions should be replaced by using a string traits class.
>> Attached is the test program I'm using...
>>
>> Thanks for your help...
>>
>> Pablo
>>
>>
>>
>
> 


March 31, 2005
Here's the Arturius output. Very encouraging so far:

        arcc.debug -c --exception-handling=on --announce-tools --compilers=bcc/5.6,cw/8,dm/beta-stlport,gcc/3.2,gcc/3.4,icl/7,icl/8,vc/6,vc/7,vc/7.1,v
c/8 -I..     -IH:\STLSoft\Identities\STLSoft\stlsoft   -IH:\STLSoft\Identities\STLSoft\stlsoft\inprogress   -IH:\STLSoft\Identities\STLSoft\stlsoft\re
search  --output-path=.\string_algo_test.obj ..\string_algo_test.cpp
Tool: bcc/5.6
Tool: cw/8
Tool: dm/beta-stlport
Tool: gcc/3.2
Tool: gcc/3.4
Tool: icl/7
Tool: icl/8
Tool: vc/6
..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
Tool: vc/7
..\string_algo_test.cpp(15): fatal error C1507: previous user errors and subsequent error recovery halt further
compilation
Tool: vc/7.1
Tool: vc/8



"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a few comments after looking at the source...
>
> 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
> 2) The (char const* s, cch) constructor is missing the check for cch's validity also
> 3) Doesn't m_base have to be pointed to m_cstr if m_cstr is allocated (when using c_str()) ?
>
> 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?
> 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])
>
> 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?
>
> BTW, saw myself in string_view's header, thanks!
>
>
> Pablo
> 


March 31, 2005
Getting rid of the compile error is easy: just take out the typename

    typedef stlsoft_ns_qual(basic_string_view)</* typename */ STRING_TYPE::value_type> string_view; // <<<
complains/crashes here


However, then VC 6 has an internal compiler error. That's bound up with the c-string form of right_view.

If that's not used in the client code, then all is well. If it's in: ICE.

If we comment out the other right_view, then the c-string form works fine.

If we have the c-string form and the following stub version, it all works fine

    template<ss_typename_param_k C>
    const ::stlsoft::basic_string_view<C> right_view(long, long, long n, C const *s)
    {
        typedef ::stlsoft::basic_string_view<C> string_view_t;

        return string_view_t(s, n);
    }

c-string + following compilers fine

    template<ss_typename_param_k S>
    const ::stlsoft::basic_string_view<typename S::value_type> right_view(S const &s, long, long n)
    {
        typedef ::stlsoft::basic_string_view<C> string_view_t;

        return string_view_t(s.data(), n);
    }

c-string + following compiles fine:

    template<ss_typename_param_k S>
    const ::stlsoft::basic_string_view<typename S::value_type> right_view(S const &s, size_t n, long l)
    {
        typedef ::stlsoft::basic_string_view<C> string_view_t;

        return string_view_t(s.data(), n);
    }

c-string + following ICEs:

    template<ss_typename_param_k S>
    const ::stlsoft::basic_string_view<typename S::value_type> right_view(S const &s, size_t n, long l = 1)
    {
        typedef ::stlsoft::basic_string_view<C> string_view_t;

        return string_view_t(s.data(), n);
    }

It seems, then, that the ICE comes from having two forms of right_view with one template-type param and one (unsigned) integral param.

More digging required ....



"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2huui$23m1$1@digitaldaemon.com...
> Here's the Arturius output. Very encouraging so far:
>
>        arcc.debug -c --exception-handling=on --announce-tools --compilers=bcc/5.6,cw/8,dm/beta-stlport,gcc/3.2,gcc/3.4,icl/7,icl/8,vc/6,vc/7,vc/7.1,v
> 
> 8 -I..     -IH:\STLSoft\Identities\STLSoft\stlsoft   -IH:\STLSoft\Identities\STLSoft\stlsoft\inprogress   -IH:\STLSoft\Identities\STLSoft\stlsoft\re
> search  --output-path=.\string_algo_test.obj ..\string_algo_test.cpp
> Tool: bcc/5.6
> Tool: cw/8
> Tool: dm/beta-stlport
> Tool: gcc/3.2
> Tool: gcc/3.4
> Tool: icl/7
> Tool: icl/8
> Tool: vc/6
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside a template declaration
> Tool: vc/7
> ..\string_algo_test.cpp(15): fatal error C1507: previous user errors and subsequent error recovery halt further
> compilation
> Tool: vc/7.1
> Tool: vc/8
>
>
>
> "Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2flvs$2jic$1@digitaldaemon.com...
>>I was looking at string_view to figure out how to implement BASIC-style left$, right$ and mid$ functions here's a few comments after looking at the source...
>>
>> 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
>> 2) The (char const* s, cch) constructor is missing the check for cch's validity also
>> 3) Doesn't m_base have to be pointed to m_cstr if m_cstr is allocated (when using c_str()) ?
>>
>> 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?
>> 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])
>>
>> 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?
>>
>> BTW, saw myself in string_view's header, thanks!
>>
>>
>> Pablo
>>
>
> 


March 31, 2005
Great!

You tweaked first it right? I very much doubt it would've compiled that
cleanly on all compilers!
Handy tool Arturius, BTW...

"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:d2huui$23m1$1@digitaldaemon.com...
> Here's the Arturius output. Very encouraging so far:
>
>        arcc.debug -c --exception-handling=on --announce-tools --compilers=bcc/5.6,cw/8,dm/beta-stlport,gcc/3.2,gcc/3.4,icl/7,icl/8,vc/6,vc/7,vc/7.1,v
> 
> 8 -I..     -IH:\STLSoft\Identities\STLSoft\stlsoft   -IH:\STLSoft\Identities\STLSoft\stlsoft\inprogress
>    -IH:\STLSoft\Identities\STLSoft\stlsoft\re
> search  --output-path=.\string_algo_test.obj ..\string_algo_test.cpp
> Tool: bcc/5.6
> Tool: cw/8
> Tool: dm/beta-stlport
> Tool: gcc/3.2
> Tool: gcc/3.4
> Tool: icl/7
> Tool: icl/8
> Tool: vc/6
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside
> a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside
> a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside
> a template declaration
> ..\string_algo_test.cpp(21): error C2899: typename cannot be used outside
> a template declaration
> Tool: vc/7
> ..\string_algo_test.cpp(15): fatal error C1507: previous user errors and
> subsequent error recovery halt further compilation
> Tool: vc/7.1
> Tool: vc/8


March 31, 2005
"Pablo Aguilar" <paguilarg@hotmail.com> wrote in message news:d2hvii$248v$1@digitaldaemon.com...
> Great!
>
> You tweaked first it right? I very much doubt it would've compiled that cleanly on all compilers!

Barely

> Handy tool Arturius, BTW...

Yes. I *really* need to get it out to the world. ;$


March 31, 2005
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();
        }
    };

    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);
    }


« First   ‹ Prev
1 2