Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have code whereby I can query a structure for a std::set of objects of type A that all match some criteria. I will very often want my query criteria to be such that the code returns a set containing only one object. And in these cases, I will want my code to fail if the query hasn't produced only one result. So I would like to make a function
A& deref_or_throw(std::set<A> s)
{ if (s.size() != 1) throw ...; return *s.begin(); }
that throws if the set contains more than one (or no) element, and dereferences the first element otherwise.
For brevity, I thought to overload the indirection operator, which is not defined for std::set:
A& operator*(std::set<A>& s) {return deref_or_throw(s);}
Is this a bad idea? It does fit with the concept of the indirection operator that it performs a dereferencing. But I could not find a strict definition of what the indirection operator should do according to the standards, so as to make sure whether I'm perverting its standard use (too far).
Don't overload operator* in this way. One person's brevity is another person's obfuscation.
In this case there is no precedent for operator* operating on any standard container so in the future if anyone looks at the code they will have no idea what it does without the finding the implementation of your operator*. Instead, take the extra 10 seconds now to copy-paste your function call name and save your future maintainers who knows how much time hunting down the operator overload a year from now.
I would suggest maybe something like *ensure_single_element(your_set).begin() or something where it's quite clear what's going on.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last year.
Improve this question
I've been practicing with operator overloading in order to comprehend it better and I came across using the << operator with vectors like this:
void operator<<(std::vector<int> &vector, int value){
vetor.push_back(value);
}
Now I know that this isn't really a good idea and that I should avoid doing this but I'd like to listen to someone more experienced in the subject in order to help me understand the << operator and the ostream class in a better way.
Now I know that this isn't really a good idea and that I should avoid doing this
Your knowledge is correct. There are two issues with this:
It's a bad idea to define operators that don't involve your own types. Technically, the standard doesn't guarantee that it won't add a global operator<<(std::vector<int> &, int) in future, which would break the forward compatibility of a program that defines such overload.
Furthermore, library programmers with the same bad idea may potentially make the same decision, breaking the compatibility with your program. This makes such idea extra bad for library code.
Unlike functions, operators don't have names that describe them so as a rule of thumb in order to keep programs understandable, operator overloads should ideally implement operations that are analogous to their built-in counterparts.
There is precedent for violation of this rule of thumb in the standard library, such as character output stream insertion operator, and the range adaptor pipe operator. Such approach increases the number of different things one operator means, and it should not be taken lightly.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
var list = new List<object>();
if (list.Any())
if (list.Count > 0)
if (list.FirstOrDefault() != null)
I can think of three reasons why Any is better than the other 2 options:
Any conveys the intent most cleanly
If the collection is not an ICollection<T>, which has a built-in Count property, then Count() will traverse the whole collection. Any() will at worst stop iterating if, well, any element is found.
FirstOrDefault() == null only works on collections of types where the default is actually null. It will not work on, say, a list of integers
There could also be edge cases which make the third option give wrong results. FirstOrDefault() == null could return true if there's some bizarre equality operator overload that returns true if an object is "equivalent" to null. That seems unlikely, but it could give a false positive for an "empty" collection.
If the collection is not an ICollection, then there should not be any meaningful performance difference between the three. The only other reason there would be a difference is if the collection implements ICollection<T> but has a strange override of GetEnumerator that does significantly more work even to just see if there is one item. That seems unlikely enough that I would only use Count in very specific circumstances with a significant, measurable performance benefit overall (not just compared to Any)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
An std::optional<T> can be initialized to the disengaged state like so:
std::optional<int> oi { nullopt };
but also like so:
std::optional<int> oi { };
and similarly for assignment (oi = {} or oi = nullopt).
Other than personal preference / sense of aesthetics, is there a difference between these which should make me prefer one over the other? Or does it not matter at all?
Note: I'm asking about cases where I want to explicitly initialize the optional, rather than default-initialize it (e.g. for emphasis).
It does not matter at all. Choose whatever makes your colleagues understand your code better.
They both have the same effect - I would prefer the simplest form (KISS), but it is subjective, pick one and be consistent. You may also wish to be consistent with how you treat other objects in your code, do you normally rely on default initialization (e.g. int i{} vs int i{0})?
Personally when I see redundant code, like initalizing an object to its default value explicitly, it does reduce my confidence in the author by a slight margin - does the author really understand what he is doing and trying to be extra safe / explicit / readable, or was he simply too lazy to read the documentation? It makes me wonder, does the author understand what happens when he writes std::vector<std::optional> v(n), or more complex examples? If this is a documented decision, in a coding style, then all is fine, I can understand the need to improve readability.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Today we discovered that the functors for multiplying and dividing, are called std::multiplies and std::divides, as opposed to, for example, std::multiply and std::divide respectively.
This is surprising to say the least, considering that std::plus and std::minus are not formulated the same way.
Is there a particular reason for the difference?
It looks like this is nothing more than a blooper: plus and minus are even not verbs...
The name themselves are not C++14 originals: C++14 just adds the <void> specialization, but the typed version and all other <functional> header stuff exist from C++98 (and even pre-iso), and certain coding convention (functions as verbs, object as substatives interface as adjectives...) were not yet already well established.
What C++14 does is just add one more feature to existing definitions letting existing code to continues to works as is. It simply cannot redefine names.
That said, consider also that the + sign is not always used across the entire standard library for add: in std::strings it is concatenation, and std::plus, if applied to strings, concatenates them. Similarly, the * is often used as a "closure" operation (think to boost::spirit).
A more proper "from scratch" library will most likely call them neutrally as cross, dash, star and slash, letting the classes that provides the corresponding operations to give them consistent names in their own context
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
My intuition and practice for a long time has been to avoid out params if at all possible. I believe that a function should have one logical purpose and that usually implies one return type (not returning multiple things). Sometimes, returning multiple things is desirable (f.e. std::map::insert). I know this can be done as a pair/tuple or as output params; the argument of which of those to use is less important to me.
What are the conceptual, design, or performance reasons to prefer either output parameters or return values?
You're right, out parameters are not really needed as RVO makes returning by value feasible, even with large types. And having to return multiple things is either a code smell, or can be sensibly packed in a structure.
I'd say the only remaining reason, and it's a biggie, is consistency. If the class already has tens of methods returning by parameter, stick to it (unless you have the liberty to refactor the darn thing :).
Depending on the context, a third alternative might be to pass a callback. The callback might have multiple methods if the called function "produces" multiple values.
Though a function that takes a callback argument doesn't really fit the definition of a "function", neither does a function that returns multiple values, IMO.