Thread: string operation and related exception

  1. #16
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Yes, which is why I like a choice. I don't like the idea that just because I use the index operator instead of at(), I forgo any such out of bounds checks. If at does it, then the index operator should too.
    I think that the whole point of having the at() member function was to provide a version of accessing by index that throws out_of_range for an invalid index. If not for this, they should have scrapped it and just let operator[] perform the index check and throw exceptions.

    The way I see it, the design choice is to allow the user of the class the choice by selecting the appropriate function. If you always want an invalid index to result in an exception being thrown, then always use at().
    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

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Which is very good, don't get me wrong. But I would like to use the index operator and get an exception thrown for out of bounds, too (or not, depending on my choice). Consistency.
    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. #18
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    So then you would also like a third function to provide fast access without overhead?

    If you use the other techniques you mentioned, then how would you be able to write some code that checks bounds and other code is fast on the same container?

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Sample:
    Code:
    std::vector<int> myv;
    myv.resize(100);
    myv.EnableExceptions(true);
    try { int n = myv[101]; /* Will throw exception */ } catch(...) { }
    try { int n = myv.at(101); /* Will throw exception */ } catch(...) { }
    myv.EnableExceptions(false);
    int n = myv[101]; // Will not throw exception
    n = myv.at(101); // Will not throw exception
    Something like that.
    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. #20
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You've not answered my point about speed.
    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. #21
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    hmm... I suspect that this may have to be a compile time option instead, maybe by means of templates, or something as dirty as a macro.

    The problem is that with this EnableExceptions() option, it implies that operator[] must first check if the option is set. If it is set, then check the range. But this check costs something that the original operator[] does not pay.

    You've not answered my point about speed.
    Ah yes, I'm repeating your point.
    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

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It's true, it might add a very, very small overhead with some checking, in which you could simply make two versions of the class that derive from a common base, one with out of bounds checking, one with not, or by some other compile time means. It's not impossible.
    Or perhaps, if that is overkill, one could do a simple global define which says use exceptions or not.
    The point is, that I would like to use the index operator and allow it to throw out of bounds, and at the same time, I want to be able to use it while it does not throw out of bounds.
    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.

  8. #23
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    I suspect that this may have to be a compile time option instead, maybe by means of templates, or something as dirty as a macro.
    Doesn't solve Daved's objection.
    How about switching between at() and []?

    The point is, that I would like to use the index operator and allow it to throw out of bounds, and at the same time, I want to be able to use it while it does not throw out of bounds.
    So basically, you're throwing a tantrum because you can't use this bit of syntactic sugar exactly the way you want?


    Oh, and very small overhead? You're talking about the difference between a single load which gets inlined and a branch. Because of a vector's typical access pattern in the case where the checking is not desired, we're talking about L1-cached loads and a check that is effectively never true.
    Last edited by CornedBee; 02-27-2008 at 11:06 AM.
    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

  9. #24
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    How about switching between at() and []?
    How?
    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

  10. #25
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Nah, not a tantrum, but because it's more like I don't like. I would prefer it to be more to my taste. I don't really like using at() just because I want exceptions thrown. I want it to emulate an array, so it's better to use the index operator.
    There are a lot of things I don't agree with in the STL.
    But besides, many classes allow for custom allocators, which is a very powerful feature, so why not this? Is it too subtle perhaps?
    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. #26
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The only objection I can see to the current setup is if you want to be able to turn on and off range checking without modifying code.

    However, I think some implementations already provide this by adding range checking in debug mode. That's good enough for me, although perhaps not completely ideal.

  12. #27
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Changing it on-the-fly is the best option, of course, but it doesn't have to be that. It could be an option at the time of creating the class.
    You could use a custom module for (such as the allocator for other classes) checking out of bounds or not, allowing you to switch on the fly, if you wanted.
    Or you could use a little hack such as a function pointer that pointed to the correct function (either one that does out of bounds checking or not). Pointer could easily be changed at runtime and it would provide no overhead (except for maybe not inlining some function).
    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. #28
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by laserlight View Post
    How?
    By making the decision in which parts of the code it makes sense to check for out-of-bounds and using at() there.

    Leave the debugging help to the assertion within [].

    Quote Originally Posted by Elysia View Post
    I don't really like using at() just because I want exceptions thrown. I want it to emulate an array, so it's better to use the index operator.
    The majority of use cases doesn't need out-of-bounds checks, to they get the syntax sugar.

    But besides, many classes allow for custom allocators, which is a very powerful feature, so why not this? Is it too subtle perhaps?
    Too static. The allocator is fixed for the type. That's fine for an allocator. It's not fine for the throwing behaviour of element-wise access. That's why there's two accessors and you can choose the appropriate one.
    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. #29
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi CornedBee,


    Here is the current implementation of STL vector from Visual Studio 2008. Looks like for operator[], both release and debug version checks for boundary. So how about your points of performance improvements and speed? Any comments?

    Code:
    #if !defined (_HAS_ITERATOR_DEBUGGING)
    	#if defined (_DEBUG)
    		#define _HAS_ITERATOR_DEBUGGING	1	/* for range checks, etc. */
    	#else
    		#define _HAS_ITERATOR_DEBUGGING	0
    	#endif	/* defined (_DEBUG) */
    #else
    
    	reference operator[](size_type _Pos)
    		{	// subscript mutable sequence
    
     #if _HAS_ITERATOR_DEBUGGING
    		if (size() <= _Pos)
    			{
    			_DEBUG_ERROR("vector subscript out of range");
    			_SCL_SECURE_OUT_OF_RANGE;
    			}
     #endif /* _HAS_ITERATOR_DEBUGGING */
    		_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
    
    		return (*(_Myfirst + _Pos));
    		}
    
    
    
    
    	reference at(size_type _Pos)
    		{	// subscript mutable sequence with checking
    		if (size() <= _Pos)
    			_Xran();
    		return (*(begin() + _Pos));
    		}
    
    
    	static void _Xran()
    		{	// report an out_of_range error
    		_THROW(out_of_range, "invalid vector<T> subscript");
    		}
    Quote Originally Posted by CornedBee View Post
    It's consistent with C syntax, and the expectation is that all implementations, in release mode, are also consistent with C, i.e. they simply allow the out-of-bounds access.

    regards,
    George

  15. #30
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The release version only has range checking if the _HAS_ITERATOR_DEBUGGING symbol is defined and set to 1. My guess is that by default it is not, so by default the release version skips the range check.

    So what you're seeing is that the code follows what CornedBee stated, and additionally implemented Elysia's preference that there be a switch of some kind to allow boundary checking even in release build.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  2. Looking for examples for string related programs
    By koloth in forum C Programming
    Replies: 5
    Last Post: 04-14-2003, 11:57 PM