2

I am writing a fuzzy logic header in c++ and tried to do the following.

typedef float fuzzy;
fuzzy operator !();

To which the compiler had this to say.

error: ‘fuzzy operator!()’ must have an argument of class or enumerated type

I know that I could write a class that would handle this (probably mush faster than it will take to ask this question), but that seems like overkill as such a class would literally have only 1 data member and only constructor and assignment member functions. All of which are superfluous as there is only 1 data member and it would be handled as if it were a float. The other operators would presumably be implemented as non-member functions. So the class would essentially be a float, except for it's customized logical and bitwise operators.

Is it possible to use a typedef to create a customized version of a built-in (a sort of pseudo class)? From what I can find, typedefs are mostly used to reduce the number of places a programmer might have to change types in the event that some environment defines/handles it's types differently.

Maybe I'm crazy, but this seems like one of the most logical and desirable ways to use a typedef. Is there some reason why this is a bad idea, or just not possible?

spike.barnett
  • 170
  • 1
  • 8
  • No. Typedefs create a type alias, and are interchangeable with the original type. Thus your proposed operator overloads will apply to all `float`s, which is obviously a bad idea. – T.C. Jun 24 '14 at 17:29
  • @DrewDormann Adding a fuzzy argument yields the same error. As for the bool return type, that defeats the whole point of fuzzy logic, which is fractional truth values. – spike.barnett Jun 24 '14 at 17:35
  • @T.C. Is there a reason why it's an alias and not a copy. Sort of like class inheritance? – spike.barnett Jun 24 '14 at 17:37
  • @DrewDormann As stated before, adding an input type does not change anything. error: ‘fuzzy operator!(fuzzy)’ must have an argument of class or enumerated type – spike.barnett Jun 24 '14 at 17:47
  • Originally, probably because it's how it worked in C, which doesn't have any concept of inheritance. Nowadays it's impossible to change without creating massive compatibility issues. Also, the ability to have type aliases is a useful feature (e.g., you'd probably want `std::vector::value_type` to be actually `double`). See also [this question](http://stackoverflow.com/questions/8182910/why-arent-typedefs-strongly-typed). – T.C. Jun 24 '14 at 22:33

1 Answers1

5

A typedef does, like an using fuzzy = float;, not introduce a new type, but an alias.

Thus, fuzzy is the same type as float and you cannot overload operators for built-in types.

So if you would, for what ever reason, need to overload operators for fuzzy, it must be a class or a struct:

struct fuzzy {

    float data_;

    // Put constructors here
    // Put conversion to float here if desired

};

Then you can define your own operators like:

std::ostream& operator << (std::ostream& os, const fuzzy& f) {
    os << "Hello from fuzzy!\n" << f.data_;
    return os;
}
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • I do not understand what kind of bitwise operations would make sense on float anyway. – Baum mit Augen Jun 24 '14 at 17:35
  • Fuzzy logic commonly makes use of different kinds of AND and different kinds of OR. That is to say, one type of AND may be to use the smaller of the two values given, where as the other might be to use a probabilistic and function on the two given values. So one might overload && for one type and & for another. – spike.barnett Jun 24 '14 at 17:44
  • 1
    You would be correct in assuming bitwise operations make no sense when applied directly to a floating point number. http://stackoverflow.com/questions/1723575/how-to-perform-a-bitwise-operation-on-floating-point-numbers The only time I ever see this is researching the underlying behavior of the system, or some reeeeeally bad APIs. – Cloud Jun 24 '14 at 17:45
  • @spike.barnett Overloading `&&` and `||` is pretty dubious because you cannot guarantee the short circuiting behavior the standard ones have. In such cases, better give it a name like `bool fuzzyAND (fuzzy,fuzzy);`. This would work with typedefs too. – Baum mit Augen Jun 24 '14 at 17:51
  • @BaummitAugen That's basically what I did originally. `float fuzAnd (float, float)` but I thought there must be some better way to do it. Perhaps not. – spike.barnett Jun 24 '14 at 17:55
  • @spike.barnett In my opinion, that is the best way. An operator should always do what the naive reader expects them to. [Interesting read on that topic.](http://stackoverflow.com/questions/4421706/operator-overloading) – Baum mit Augen Jun 24 '14 at 17:58