Thread: Though implementation problem

  1. #61
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Elysia View Post
    I see that as a problem with the documentation. Obviously they didn't document it good enough! You could run into the same problem if the free functions weren't documented either!
    The thing is... if they documented it properly, then that class would be easier to use than free functions (or at least for me), although modifying it might be another matter...
    Well it's definitely a problem with documentation (or lack thereof), but from what I saw from the names of the functions, I think that class should have been broken up into several different classes, but instead if became a dumping ground for anything and everything whether it belongs there or not.

    Quote Originally Posted by citizen
    std::basic string has like 107 member functions
    I never bothered to count them, but wow! Is it really that many?

  2. #62
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Quote Originally Posted by Elysia View Post
    Std::string is one of the most unhelpful string classes I've seen. Replace is fatefully misnamed.
    This is a matter of semantics. I find boost's replace_all is better named than your Replace.

    Find_first_of, for example, is also inappropriate named. It should be named more similarly to find_any_first_of or the like since it finds any of the characters in the string, not the entire phrase.
    I'm not a native speaker, but of in this sense means exactly the same as "any of" or one of ...
    The replace function is misleading into believing it can search and replace a given occurrence of a string with another. Further, it does not reallocate or move data (I think?), so if you replace "Alice" with "Jonathan" you're going to overwrite data.
    I think the arguments that string::replace take makes it quite clear what it does, namely, replace a certain number of characters at a certain position with another string (or a part of it). It is not a nice function, though, and it seems that even this reference doesn't get it quite right.

    The std::replace is also flawed in that it can only replace single characters with another given character (if I remember this correctly). Who needs that? When I replace, I replace strings.
    It is primarily not a string algorithm.

    All in all, I agree that std::string is lacking a lot of things for high-level string manipulation. However, does that mean everybody should rewrite their own string class?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #63
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by anon View Post
    This is a matter of semantics. I find boost's replace_all is better named than your Replace.
    I think the arguments that string::replace take makes it quite clear what it does, namely, replace a certain number of characters at a certain position with another string (or a part of it). It is not a nice function, though, and it seems that even this reference doesn't get it quite right.
    Perhaps. Perhaps not. But if I see "replace," it sounds to me like it's going to replace all occurrences. That's what the name implies to me.

    I'm not a native speaker, but of in this sense means exactly the same as "any of" or one of ...
    In that case, it could take a vector of chars (although I think I can see why it doesn't...). Then it wouldn't be unambiguous anymore. But since it takes a string, it's name is misleading IMO.

    It is primarily not a string algorithm.
    But for all the power and functionality, it seems to lack some very common operations!?
    So much for a string class. It's not a string class if it lacks a way to do common operations such as replacing strings.

    All in all, I agree that std::string is lacking a lot of things for high-level string manipulation. However, does that mean everybody should rewrite their own string class?
    No, of course not. I just wanted to do one that suited me better.
    And hey look - it has turned into something so much bigger which is giving a lot of experience and classes that I can reuse later (iterator, and range iterator too, which I'm working on!).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #64
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    All in all, I agree that std::string is lacking a lot of things for high-level string manipulation. However, does that mean everybody should rewrite their own string class?
    I think they should do a backwards incompatible complete rewrite of the standard library with the advantage of hindsight, and then provide this new library parallel to the current standard library (which would then be deprecated) for the sake of the huge amount of code that depend on it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #65
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Hey, that's what I'm doing for the I/O library.

    Elysia, while reading this thread, something occurred to me. If I recall correctly, you've several times stated that std::string should be properly derivable, so that people can create subclasses with additional high-level manipulation functions. You made an argument against free functions in namespaces because they are not associated with std::string and aren't as easily found in the documentation.

    This makes me wonder. Have you considered that the member functions of mystring are just as difficult, if not more so, to find for the std::string-user as free functions?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #66
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by laserlight View Post
    I think they should do a backwards incompatible complete rewrite of the standard library with the advantage of hindsight, and then provide this new library parallel to the current standard library (which would then be deprecated) for the sake of the huge amount of code that depend on it.
    or just put it in std2 namespace or something.

    BTW Elysia, rather than creating a new string class (since we already have so many to choose from), why not create some string algorithms and put them in a StrUtils namespace like I did.
    That way, a few years from now, if you decided you don't like CString anymore and want to use std::string, you can still use all those string algorithms on the other string classes.
    The syntax might be a bit uglier, but you can write things like:
    Code:
    StrUtils::ToUpper( str.begin(), str.end() );
    To convert the string (whatever its type may be) into upper case.

  7. #67
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by CornedBee View Post
    Elysia, while reading this thread, something occurred to me. If I recall correctly, you've several times stated that std::string should be properly derivable, so that people can create subclasses with additional high-level manipulation functions.
    Although std::string is not supposed to be derived from, I don't see the harm of doing it if all you are doing is adding convenience functions. Just stay away from the private internals, use the already-provided public interfaces, and you should be okay.

    It won't be virtually destructed, but that doesn't matter if you haven't added anything to the implementation.

  8. #68
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by CornedBee View Post
    Elysia, while reading this thread, something occurred to me. If I recall correctly, you've several times stated that std::string should be properly derivable, so that people can create subclasses with additional high-level manipulation functions. You made an argument against free functions in namespaces because they are not associated with std::string and aren't as easily found in the documentation.
    I don't think I've ever stated it about the std::string is particular, but I would love the STL to be derivable friendly.

    This makes me wonder. Have you considered that the member functions of mystring are just as difficult, if not more so, to find for the std::string-user as free functions?
    No, not really. It just seems an advantage to me putting them in the same place.

    Quote Originally Posted by cpjust View Post
    BTW Elysia, rather than creating a new string class (since we already have so many to choose from), why not create some string algorithms and put them in a StrUtils namespace like I did.
    That way, a few years from now, if you decided you don't like CString anymore and want to use std::string, you can still use all those string algorithms on the other string classes.
    The syntax might be a bit uglier, but you can write things like:
    Code:
    StrUtils::ToUpper( str.begin(), str.end() );
    To convert the string (whatever its type may be) into upper case.
    Sure, I'm working on trying to rip out all those functions into a namespace, say, Strings::Mainpulation (could use some work on that name). But I will still keep the members as wrappers.
    But even so, right now I'm working on something even more intriguing which actually might (or might have) benefited the standard library.

    Right now, I'm fixing up my range iterator. On the outside, it's just a normal iterator, but on the inside, it's not a single pointer or single address or single element, but rather a range.
    What might this be good for, you ask? It can specify a range and emulate that range as a single object.
    I was thinking of a new implementation of Find.
    Basically, you call find to find a word (no range or anything), and it will return a Result class.
    The result class have several member to control and attain the data you want. For example, say you seek for "is" in "This is very fun it is". The class would have some functions such as Next, which would set the internal state to the next position where "is" was found. Previous goes backwards. If you want, you can just call Get to get a range (or the entire string) of where the "is" are.
    So say you get position 1 where "is" was encountered. It would return a range iterator that emulates the range 6 to 7 in the string. If you do *, it would return a std::string with your data. And if you try to assign it, you could easily replace that "is" with something else, even if longer.
    Something like:

    Code:
    Strings::CStringEx MyStr = "This is a test";
    Strings::SerachResult search_result = MyStr.Find("is");
    Strings::CStringExItRange it = search_result.GetFirst();
    cout << MyStr << endl; // Prints "This is a test"
    cout << *it << endl; // Prints "is"
    *it = "is not";
    cout << *it << endl; // Prints "is not"
    cout << MyStr << endl; // Prints "This is not a test"
    search_result = MyStr.Find("not ");
    MyStr.Erase( search_result.GetFirst() );
    It's a very cool concept that might actually have a lot of uses.
    But even being able to sort, and mess around with your results after Find is even better - more control which could be added for any string class. These are all members, but could be broken out to free functions.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #69
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    I think you'll have to find some other name; what you describe is very definitely not a range iterator, but is instead a kind of insertion iterator; then, 'range_inserter' is probably a good name.

    But even so, right now I'm working on something even more intriguing which actually might (or might have) benefited the standard library.
    The STL already supports this goal by providing many generic functions. You only need a better interface--because as I've said, it can be verbose.

    The code I provided below should work, but it isn't tested either.

    Edit: In retrospect, the container type should be a required template parameter--not derived from a function parameter. With this is mind the function could take the target contents as a range, as for the old and new contents, and return an iterator to the last element yielding the much more sophisticated:

    Code:
    my_container_instance.erase(replace_range<my_container_type>(my_container_instance.begin(), my_container_instance.end(), old_contents.begin(), old_contents.end(), new_contents.begin(), new_contents.end()), my_container_instance.end());
    Which has the bonus of allowing 'replace_range_all' to be written quite simply.

    Soma

    Code:
    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <string>
    
    template
    <
      typename element_F
    >
    struct rollover
    {
      element_F operator ()
      (
        const element_F & value_f
      )
      {
        return(value_f);
      }
    };
    
    template
    <
      typename element_F
    >
    struct rollover_left
    {
      element_F operator ()
      (
        const element_F & value_f,
        const element_F & ignored_f
      )
      {
        return(value_f);
      }
    };
    
    template
    <
      typename element_F
    >
    struct rollover_right
    {
      element_F operator ()
      (
        const element_F & ignored_f,
        const element_F & value_f
      )
      {
        return(value_f);
      }
    };
    
    template
    <
      typename container_F
    >
    void replace_range
    (
      container_F & container_f,
      const typename container_F::const_iterator old_contents_beginning,
      const typename container_F::const_iterator old_contents_ending,
      const typename container_F::const_iterator new_contents_beginning,
      const typename container_F::const_iterator new_contents_ending
    )
    {
      const typename container_F::difference_type old_contents_size(std::distance(old_contents_beginning, old_contents_ending));
      const typename container_F::difference_type new_contents_size(std::distance(new_contents_beginning, new_contents_ending));
      if(old_contents_size >= new_contents_size)
      {
        typename container_F::iterator modifier(std::search(container_f.begin(), container_f.end(), old_contents_beginning, old_contents_ending));
        typename container_F::iterator container_cursor(std::transform(new_contents_beginning, new_contents_ending, modifier, rollover<typename container_F::value_type>()));
        std::advance(modifier, new_contents_size);
        std::advance(container_cursor, old_contents_size - new_contents_size);
        container_f.erase(std::copy(container_cursor, container_f.end(), modifier), container_f.end());
      }
      else
      {
        typename container_F::iterator container_cursor(std::search(container_f.begin(), container_f.end(), old_contents_beginning, old_contents_ending));
        container_cursor = std::transform(old_contents_beginning, old_contents_ending, new_contents_beginning, container_cursor, rollover_right<typename container_F::value_type>());
        std::insert_iterator<container_F> modifier(container_f, container_cursor);
        typename container_F::const_iterator replacement_cursor(new_contents_beginning);
        std::advance(replacement_cursor, old_contents_size);
        std::copy(replacement_cursor, new_contents_ending, modifier);
      }
    }
    
    int main()
    {
      std::string message("This is a test.");
      std::string is(" is ");
      std::string correction(" is not ");
      replace_range(message, is.begin(), is.end(), correction.begin(), correction.end());
      std::copy(message.begin(), message.end(), std::ostream_iterator<std::string::value_type>(std::cout, ""));
      std::cout << '\n';
      replace_range(message, correction.begin(), correction.end(), is.begin(), is.end());
      std::copy(message.begin(), message.end(), std::ostream_iterator<std::string::value_type>(std::cout, ""));
      std::cout << '\n';
      return(0);
    }
    Last edited by phantomotap; 05-12-2008 at 03:23 PM.

  10. #70
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    I think you'll have to find some other name; what you describe is very definitely not a range iterator, but is instead a kind of insertion iterator; then, 'range_inserter' is probably a good name.
    I don't know about that. It's an iterator alright. You can definitely view the current value, its keys (starting and ending), plus set it to something else, just as you can modify a normal iterator.
    You should also be able to traverse using ++, --, etc, so I fail to see how it is anything but an iterator for a range of elements.

    But that example of yours looks really complicated (like anything with a lot of templates aren't...), so I may have to look over it more properly at a later time.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #71
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Elysia View Post
    It just seems an advantage to me putting them in the same place.
    My point was that they're not.

    It's a very cool concept that might actually have a lot of uses.
    Oh, yes. It's also very similar to Boost.Tokenizer's token_iterator and Boost.Regex's regex_iterator and regex_token_iterator. Those aren't mutable, though.

    It seems as if you're slowly getting the idea of generic programming.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #72
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    It's an iterator alright.
    I didn't say it wasn't. I said it wasn't a "range iterator", and it isn't. An iterator by definition supports the traversal of a range--if there is more than one element; that alone doesn't make it a range iterator. A range iterator like a random access iterator implies particular abilities above and beyond what a normal iterator provides.

    But that example of yours looks really complicated (like anything with a lot of templates aren't...), so I may have to look over it more properly at a later time.
    You probably should... implementing a generic 'range_inserter' would be trivial if you can dissect what I wrote.

    Soma

  13. #73
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Phantomatap, I believe in this case you have a very specific idea of what a range iterator is to you, but that doesn't mean Elysia's use of the word is incorrect.
    It's not very useful, though.

    See, Elysia, the problem with range_iterator is this: a range, in C++, is a sequence specified as a pair of iterators (to the first elements and past the last element). Because of this, every iterator iterates over a range, which makes the name range_iterator kinda superfluous.
    A better name would be subrange_iterator, because its element type is a subrange of the range it traverses.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  14. #74
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by CornedBee View Post
    See, Elysia, the problem with range_iterator is this: a range, in C++, is a sequence specified as a pair of iterators (to the first elements and past the last element). Because of this, every iterator iterates over a range, which makes the name range_iterator kinda superfluous.
    A better name would be subrange_iterator, because its element type is a subrange of the range it traverses.
    I think not quite. A range iterator should still be able to walk forwards/backwards, only not per element, as in a traditional iterator. Instead it treats a range as one element and it should be obvious by this since it emulates this behaviour by implementing two iterators to keep track of start and end.
    In my previous search example, if we found two "is" in the strong, we could walk among those results via the operator by using ++/--. The only difference between the range iterator and a normal iterator here is that the range iterator treats the whole word "is" as one element, as opposed to a normal iterator which would treat individual characters as one element.

    If I take the previous example:
    Code:
    Strings::CStringEx MyStr = "This is a test, that it is.";
    Strings::SerachResult search_result = MyStr.Find("is");
    Strings::CStringExItRange it = search_result.GetFirst();
    cout << MyStr << endl; // Prints "This is a test, that it is."
    cout << *it << endl; // Prints "is"
    *it = "is not";
    cout << MyStr << endl; // Prints "This is not a test, that it is."
    it++;
    *it = "is not";
    cout << MyStr << endl; // Prints "This is not a test, that it is not."
    It iterates through the found matches in this example, just as a normal iterator would, only it treats the range from the 'i' to 's' as a single element. This way it can be implemented in a more advanced way.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #75
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Phantomatap, I believe in this case you have a very specific idea of what a range iterator is to you, but that doesn't mean Elysia's use of the word is incorrect.
    Yes, it does, or are you discounted all technical names/jargon? The phrase implies some very specific capabilities. If he said he was designing an interface for an iterator that only supported '++' but called it a random access iterator would you tell him to call it something else?

    See, Elysia, the problem with range_iterator is this: a range, in C++, is a sequence specified as a pair of iterators (to the first elements and past the last element). Because of this, every iterator iterates over a range, which makes the name range_iterator kinda superfluous.
    The problem with this entire idiotic comment becomes obvious if you had actually read what has been posted. That is, ignoring comments relating to the poor attempt at describing a range in terms of the word "sequence", your left with nothing I didn't say. I specifically told him not to call it a range iterator. What I suggested was 'range_inserter' implying an iterator using a insertion mechanic over a specific range regardless of the number of pre-existing elements.

    A better name would be subrange_iterator, because its element type is a subrange of the range it traverses.
    That would not be a better name for this. That probably implies something very specific as well, but I don't know what it would be. At the very least it would be called 'subrange_inserter'.

    Instead it treats a range as one element and it should be obvious by this since it emulates this behaviour by implementing two iterators to keep track of start and end.
    Ah, in that case, you do want a range iterator. I misunderstood the intent of your illustrative source. Sorry.

    Ah, nope... you are still talking about inserting additional contents back in to the original container.

    Soma
    Last edited by phantomotap; 05-12-2008 at 03:58 PM. Reason: 1): Elysia | 2): Silly...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM
  2. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  3. implementation file
    By bejiz in forum C++ Programming
    Replies: 5
    Last Post: 11-28-2005, 01:59 AM
  4. Replies: 5
    Last Post: 11-07-2005, 11:34 PM
  5. Memory Problem - I think...
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 10-24-2001, 12:14 PM