Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create a new operator in C++ and how?

Tags:

c++

MATLAB arrays support matrix operations and element operations. For example, M*N and M.*N. This is a quite intuitive way to distinguish ‎the two different operations. If I want to implement similar operations in C++, how can I do that?

Can I create a new operator, .*, too? If yes, can anyone give me some guidance?

like image 236
shangping Avatar asked Dec 08 '11 01:12

shangping


People also ask

How do I create a new operator?

Declaration − A variable declaration with a variable name with an object type. Instantiation − The 'new' keyword is used to create the object. Initialization − The 'new' keyword is followed by a call to a constructor. This call initializes the new object.

Is there a new operator in C?

C uses the malloc() and calloc() function to allocate memory dynamically at run time and uses a free() function to free dynamically allocated memory. C++ supports these functions and also has two operators new and delete, that perform the task of allocating and freeing the memory in a better and easier way.

How do you use the new operator?

Use of the new operator signifies a request for the memory allocation on the heap. If the sufficient memory is available, it initializes the memory and returns its address to the pointer variable. The new operator should only be used if the data object should remain in memory until delete is called.

Can I create new operators using operator overloading?

New operators can not be created. 2) Arity of the operators cannot be changed. 3) Precedence and associativity of the operators cannot be changed. 4) Overloaded operators cannot have default arguments except the function call operator () which can have default arguments.


2 Answers

No, you can't overload op.*:

[C++03 & C++11: 13.5/3]: The following operators cannot be overloaded:

. .* :: ?: 
like image 129
Lightness Races in Orbit Avatar answered Sep 28 '22 16:09

Lightness Races in Orbit


In C++, there's a list of predefined operators, most of which are overloadable (.* is not). Additionally, any name can be used as an operator like:

#include <iostream>  // generic LHSlt holder template<typename LHS, typename OP> struct LHSlt {     LHS lhs_; };  // declare myop as an operator-like construct enum { myop };  // parse 'lhs <myop' into LHSlt template<typename LHS> LHSlt<LHS, decltype(myop)> operator<(const LHS& lhs, decltype(myop)) {     return { lhs }; }  // declare (int <myop> int) -> int int operator>(LHSlt<int, decltype(myop)> lhsof, int rhs) {     int& lhs = lhsof.lhs_;     // here comes your actual implementation     return (lhs + rhs) * (lhs - rhs); }  // strictly optional #define MYOP <myop>  int main() {     std::cout << (5 <myop> 2) << ' ' << (5 MYOP 2); } 

Disclaimer: This, strictly speaking, gets translated to (5 < myop) > 2, which is LHSlt<int, decltype(myop)>(5) > 2. Thus it's not a new 'operator', in C++-terms, but it's used exactly the same way, even in terms of ADL. Also, if type is large, you probably want to store const T&.

Note that you can do this with any binary operator that can be defined external to the class; precedence is based on the precedence of the two sides (< and >). Thus you can have e.g. *myop*, +myop+, <<myop>>, <myop>, |myop| in this order of precedence.

If you want right-associativity, it gets a bit more tricky. You'll need both of a RHS-holder and LHS-holder (the latter being LHSlt here) and use surrounding operators such that the right one has higher precedence than the left one, e.g. a |myop> b |myop>c is a |myop> (b |myop> c). Then you need the function for both your type and your holder type as the lhs.

like image 33
lorro Avatar answered Sep 28 '22 18:09

lorro