0

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

DanielGr
  • 191
  • 1
  • 6
  • 5
    To me it does not make sense. `*` means give me the pointed to object. I hate using operators that do something different then what they would do on a standard type. – NathanOliver Aug 01 '16 at 15:07
  • @NathanOliver: so you should not use operator `<<` for inserting objects to streams, as this is originally the bitwise left shift operator... – shrike Aug 01 '16 at 15:11
  • 2
    @shrike What do you mean by originally? When C++ was standardized in 98 it was both the sift and stream operator. Should they have made a new operator, idk. Is it to late to change it now, yes – NathanOliver Aug 01 '16 at 15:14
  • @NathanOliver: they could have invented another operator for stream insertion... they did not, so in C++ you can assume that an operator may have a different meaning than the one you expect at first time... – shrike Aug 01 '16 at 15:17
  • 4
    @shrike I disagree with that. If I ever saw code that did `foo / bar` and that was not division I would not use it. Code is hard enough to read without changing the meaning of the operators. – NathanOliver Aug 01 '16 at 15:19
  • 1
    I tend to agree with @NathanOliver. Sometimes such overloads can make sense (e.g. concatenation of `boost::filesystem::path` objects) but even then it can make understanding a codebase more difficult to learn. – Nik Bougalis Aug 01 '16 at 15:24
  • @NathanOliver, `*` gives you _a_ pointed to object. There are objects in the standard library (e.g. smart pointers, iterators) that use the indirection operator to access objects that are not their strict derefencering. That's why it's the "indirection" operator, not the "dereference" operator.Here the object indirected is a set of only one element. If the set is not truly a set of only one element, the code throws. It seems to fulfill the cursory requirements of indirection. But I, like you, have a slight uneasy feeling looking at it. I just can't fully justify that feeling. – DanielGr Aug 01 '16 at 15:24
  • @DanielGr Yes, but `operator*` doesn't usually have any parameters. – user2296177 Aug 01 '16 at 15:29
  • @user2296177, I'm not sure what you mean. `operator*` requires an argument---it must operate on _something_. – DanielGr Aug 01 '16 at 18:37

1 Answers1

2

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.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • This does not answer the question... – ciamej Aug 01 '16 at 15:34
  • 1
    The OP question I see is "is this a bad idea?". To me, this answer says, yes it is, and proposes a suitable alternative, and why (i.e. readability). – 2785528 Aug 01 '16 at 15:41
  • I put a "no, don't do this" leading sentence, leaving the existing reasoning in place. – Mark B Aug 01 '16 at 15:49
  • The op wants to know "what the indirection operator should do according to the standards" . I want too! "Don't do it, it's bad" is just an opinion. – ciamej Aug 01 '16 at 15:50
  • The question as I read it is "is it a bad idea to overload `operator*` in this unusual way?". Maybe we can get the OP to clarify their meaning. – Mark B Aug 01 '16 at 15:53
  • My question is "is my example here an unusual way?" (as you write it). Though I am convinced it's a bad idea---and have chosen to write a function called `lone_elt` instead---I would still like to know what the proper functionality should be according to the standards. Like I said, I'm convinced by the argument that this code could be confusing for users; but I'm not convinced yet that it actually doesn't conform to the proper intention of indirection. – DanielGr Aug 01 '16 at 18:40