So if I get this straight, your intention is to indicate to the user which pointers they need to check for null, since some pointers are null during normal execution and must be checked, whereas others are only null in exceptional circumstances (in which case an exception would have been thrown and there's no reason to check the pointer anyway). If this is the case, wouldn't a simple typedef serve the same purpose?
typedef Foo* NullableFooPtr; // Can be NULL, check!
typedef Foo* NonNullableFooPtr; // Can't be NULL if you get far enough to have one, no need to check
boost::optional For Pointers
yes that's his intend. together with the consistency thing, you don't have ptrs you have to check, and ptrs you don't have to, and non-pointer types you don't have to, and non-pointer-with-additional-flag that you have to.
if it's optional<T>, you have to check. else, you never have to (except with some form of exception handling for the extreme cases, but never in ordinary code flow)
if it's optional<T>, you have to check. else, you never have to (except with some form of exception handling for the extreme cases, but never in ordinary code flow)
Quote:Original post by Zipster
So if I get this straight, your intention is to indicate to the user which pointers they need to check for null, since some pointers are null during normal execution and must be checked, whereas others are only null in exceptional circumstances (in which case an exception would have been thrown and there's no reason to check the pointer anyway). If this is the case, wouldn't a simple typedef serve the same purpose?
typedef Foo* NullableFooPtr; // Can be NULL, check!
typedef Foo* NonNullableFooPtr; // Can't be NULL if you get far enough to have one, no need to check
I think a better way to indicate this is simply with a comment, personally. If there's one thing I've learned over the past few years, it's that pushing all problem solutions through a boostify_if_possible filter is not the answer, and you will regret it later on. Granted, your solution had nothing to do with boost, but it also just seems a little silly. Should a non-nullable pointer be convertible to a nullable pointer? Seems like it. What about vice versa? Ooops, probably not.
I mean, really. KISS. If some pointers should never be null, document that with a comment on the function that returns the pointer. The older I get, the more I realize that sometimes you just need to stop creating new problems and just GSD.
Quote:Original post by cache_hit
I think a better way to indicate this is simply with a comment, personally. If there's one thing I've learned over the past few years, it's that pushing all problem solutions through a boostify_if_possible filter is not the answer, and you will regret it later on. Granted, your solution had nothing to do with boost, but it also just seems a little silly. Should a non-nullable pointer be convertible to a nullable pointer? Seems like it. What about vice versa? Ooops, probably not.
I never said it was a good idea, I was only proposing an alternative that made the code more self-documenting like the OP wanted while using a basic feature of the language that introduces zero overhead, as opposed to tacking on additional libraries. I would personally use proper documentation as well.
Quote:Original post by Zipster
typedef Foo* NullableFooPtr; // Can be NULL, check!
typedef Foo* NonNullableFooPtr; // Can't be NULL if you get far enough to have one, no need to check
I'm trying, but I can't see the usefulness of this... I mean, why NonNullableFooPtr will be non-nullable at all?
If it's just a sort of reminder at the time of declaring the variable I'd rather define the actual variable as:
Foo* NonNulablePointerVariableToFoo;
I return references when it can't be null. I like boost::optional in concept, for example returning optional bounding box for a mesh which might be dynamic mesh without any geometry yet.
But I really dislike all the headers boost nowdays includes. Workarounds for every possible compiler, and optional.hpp includes half (or whole) mpl. I believe it was around 700 headers for just that. If you have around thousand source files, it does slow down the compilation and link time (alot of duplicate symbols). I've injected some predeclarations into boost namespace, but that doesnt feel right. Btw try include boost::format and put "Show Includes" on if you're with MSVC.
I'm happy we have now std smart pointers rammed into memory header, compared to boost it includes only 1/5th headers.
But I really dislike all the headers boost nowdays includes. Workarounds for every possible compiler, and optional.hpp includes half (or whole) mpl. I believe it was around 700 headers for just that. If you have around thousand source files, it does slow down the compilation and link time (alot of duplicate symbols). I've injected some predeclarations into boost namespace, but that doesnt feel right. Btw try include boost::format and put "Show Includes" on if you're with MSVC.
I'm happy we have now std smart pointers rammed into memory header, compared to boost it includes only 1/5th headers.
More on topic, don't return null pointers. IMO, try to make all functions no-fail or return null objects as said before. Asserts and exceptions (or abort()) will handle the error cases. It makes alot cleaner syntax.
Although there are exceptions. At very low-level code it might be handy to use pointer aritmethic and code closer to C, but that should be implementation details.
Although there are exceptions. At very low-level code it might be handy to use pointer aritmethic and code closer to C, but that should be implementation details.
Dave's pretty much got exactly what my intent and reasoning are. The one thing to keep in mind when suggesting an alternative is that consistency is, to me at least, as important a goal as hinting at null-ability. Specifically, non-pointer types can use optional in exactly the same way. References would be an option (maybe) if this didn't get used in factory functions and the objects weren't managed by smart pointers. I suppose introducing a new smart pointer type that holds references would be another option, but I'm not sure it meets my consistency criterion as well.
I don't like this solution because it seems to be saying that null-ability is a property of the pointer, as opposed to being a property of its usage. I think the semantics of optional<FooPtr> are closer to what's really going on, but that may just be me.
That's the thing, optional<FooPtr> effectively is the documentation. Not only that, it's a form of documentation that's always visible to the user. No need to check the docs for every function, or remember any of that--it's implicit and unavoidable in the code itself. The motivation being that this is one of this bits of documentation that's often quite easy to miss and just as easy to forget to abide by.
Quote:Original post by Zipster
typedef Foo* NullableFooPtr; // Can be NULL, check!
typedef Foo* NonNullableFooPtr; // Can't be NULL if you get far enough to have one, no need to check
I don't like this solution because it seems to be saying that null-ability is a property of the pointer, as opposed to being a property of its usage. I think the semantics of optional<FooPtr> are closer to what's really going on, but that may just be me.
Quote:Original post by cache_hit
I mean, really. KISS. If some pointers should never be null, document that with a comment on the function that returns the pointer. The older I get, the more I realize that sometimes you just need to stop creating new problems and just GSD.
That's the thing, optional<FooPtr> effectively is the documentation. Not only that, it's a form of documentation that's always visible to the user. No need to check the docs for every function, or remember any of that--it's implicit and unavoidable in the code itself. The motivation being that this is one of this bits of documentation that's often quite easy to miss and just as easy to forget to abide by.
Quote:Original post by Shinkage
Dave's pretty much got exactly what my intent and reasoning are. The one thing to keep in mind when suggesting an alternative is that consistency is, to me at least, as important a goal as hinting at null-ability. Specifically, non-pointer types can use optional in exactly the same way. References would be an option (maybe) if this didn't get used in factory functions and the objects weren't managed by smart pointers. I suppose introducing a new smart pointer type that holds references would be another option, but I'm not sure it meets my consistency criterion as well.Quote:Original post by Zipster
typedef Foo* NullableFooPtr; // Can be NULL, check!
typedef Foo* NonNullableFooPtr; // Can't be NULL if you get far enough to have one, no need to check
I don't like this solution because it seems to be saying that null-ability is a property of the pointer, as opposed to being a property of its usage. I think the semantics of optional<FooPtr> are closer to what's really going on, but that may just be me.Quote:Original post by cache_hit
I mean, really. KISS. If some pointers should never be null, document that with a comment on the function that returns the pointer. The older I get, the more I realize that sometimes you just need to stop creating new problems and just GSD.
That's the thing, optional<FooPtr> effectively is the documentation. Not only that, it's a form of documentation that's always visible to the user. No need to check the docs for every function, or remember any of that--it's implicit and unavoidable in the code itself. The motivation being that this is one of this bits of documentation that's often quite easy to miss and just as easy to forget to abide by.
I get it, trust me. I just think that simplicity is a far more noble goal to strive for than consistency.
Anyway, what does the following code snippet print?
optional<Foo> f;optional<Foo> g(NULL);if (f){ cout << "1" << endl;}else if (g){ cout << "2" << endl;}else{ cout << "3" << endl;}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement