www.digitalmars.com         C & C++   DMDScript  

c++.stlsoft - string_view in 1.8.3b4

reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
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 
Mar 30 2005
next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"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
Mar 31 2005
next sibling parent reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
"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
Mar 31 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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

Mar 31 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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


Mar 31 2005
prev sibling parent reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
"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
Apr 01 2005
parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"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.
Apr 04 2005
prev sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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
 

Mar 31 2005
next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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


Mar 31 2005
prev sibling next sibling parent reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
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

Mar 31 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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. ;$
Mar 31 2005
prev sibling next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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);
    }
Mar 31 2005
parent reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
"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
Mar 31 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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. :-)
Mar 31 2005
prev sibling next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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 */
Mar 31 2005
prev sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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);
    }
Mar 31 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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.
Mar 31 2005
parent reply "Pablo Aguilar" <paguilarg hotmail.com> writes:
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.

Mar 31 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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.


Mar 31 2005