Thread: Though implementation problem

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    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.

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

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

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

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

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

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

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

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

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

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

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    Ah, nope... you are still talking about inserting additional contents back in to the original container.
    That's not all there is to it.
    An iterator should allow you to set a new value, overwriting whatever may be there, as well as allow you to iterate through a vector or a set of results and allow you to see the keys as well as the actual value at any given element.
    It's no different from a normal iterator. It works in the exact same way.
    Replacing a value with a value of the same type. But since strings are variable, it may have to shift the data to make place. But that's really irrelevant.

    Why do you insist to call it insertion iterator?
    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.

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    Why do you insist to call it insertion iterator?
    Because shifting a piece of data to make room for something else is an insertion, by definition.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I guess, fair enough. It doesn't really matter what it's called, so long as it does what it should.
    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. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> It doesn't really matter what it's called
    Well, of course it does matter. It has to be named clearly and correctly. Otherwise you would not be able to find it if you're new to the interface and it would be difficult to use (which we know is very important to you).

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