Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#define a special operator in c++

Say that I want to make up a special operator !+ in C++ between two objects. I would like to use !+, on example, because I think it is much more meaningful than any other operator.

One basic thing I could do is to find a free, unused operator and make the replacement work with a #define:

#define !+ %
class myclass 
{
  public:
   int operator %(myclass &c)
   {
      return 3;
   }
}

So that if I later write something like

a!+b 

with a and b instances of myclass, it would work.

Now, is there any way to define it instead that with an operator, with some function? Something like:

#define a!+b -> a.operatorexclamativeplus(b)

It would make the translation much less dirty, and would allow for a potentially unlimited number of these new "fake operators"!

like image 242
Matteo Monti Avatar asked Dec 15 '22 19:12

Matteo Monti


1 Answers

"Now, is there any way to define it instead that with an operator, with some function?"

No, !+ doesn't form a valid (normal) identifier for a preprocessor macro. The characters are reserved for language intrinsic operators.

The set of characters you can use for macro definitions is [_A-Za-z][_A-Za-z0-9]*regex syntax1.

As from the c++ standards definitionsdraft section

16 Preprocessing directives

...
control-line:
...
# define identifier replacement-list new-line
# define identifier lparen identifier-listopt) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list, ... ) replacement-list new-line


UPDATE:
I've been experimenting with this a bit, since this actually is an interesting question, and if not #define'd macros, we can use overloading intrinsic operator functions for classes in c++.

I have found there actually are possible (but may be weird and unexpectedly behaving) options, to overload combinations of intrinsic operators by chaining them and keep state. The closest thing you can get for your newly introduced operator could be:

class Foo {
    enum OpState { None , PlusState , NotState };   
public:
   Foo& operator+() {
       cout << "operator+()" << endl;
       opState = PlusState;
       return *this;
   }
   Foo& operator!() {
       cout << "operator!()" << endl;
       switch(opState) {
       case PlusState:
           operatorexclamativeplus();
           break;       
       default:
           opState = NotState;
           break;       
       }
       return *this;
   }    
private:
    Foo& operatorexclamativeplus() {
       cout << "operatorexclamativeplus()" << endl;
       opState = None;
       return *this;
    }
    Foo& operatorexclamativeplus(const Foo& rhs) {
       cout << "operatorexclamativeplus(const Foo& rhs)" << endl;
       opState = None;
       return *this;
    }   
    OpState opState;
};

int main() {
    Foo x;
    Foo z = !+x;
    return 0;
}

Output

operator+()
operator!()
operatorexclamativeplus()

See live sample.


Though, because of operator precedence rules, this would work only for unary operators (! has higher precedence than binary +), the form you want to have doesn't seem to be actually achievable:

class Foo {
    // ...
public:
    // Provide an additional binary 'operator+()'
    friend Foo& operator+(Foo& lhs, const Foo& rhs) {
        cout << "operator+(Foo& lhs, const Foo& rhs)" << endl;
        if(lhs.opState == NotState) {
            return lhs.operatorexclamativeplus(rhs);
        }
        return lhs;
    }
    // ...
};

int main() {
    Foo x;
    Foo y;
    Foo z = y !+ x;
    return 0;
}

See this miserably fail.


CONCLUSION:

  1. Some overloaded combinations of intrinsic operators might be syntactically possible, regarding their precedence definitions, and maintaining state of lvalues.
  2. It's probably not a very good idea, to try to overload intrinsic operator behavior, introducing completely new semantics.

______________________________________________________________________________________

1) Regarding leading underscores (_,__) for identifiers please read the standards sections mentioned in this answer, these are syntactically valid though.

like image 127
πάντα ῥεῖ Avatar answered Dec 27 '22 20:12

πάντα ῥεῖ