Related
I'm learning about Operator Overloading at the moment on learncpp.com and came across a statement that I can't quite wrap my head around. Here it is:
When dealing with binary operators that do modify the left operand
(e.g. operator+=), the member function version is typically preferred.
In these cases, the leftmost operand will always be a class type, and having the object being modified become the one pointed to by
*this is natural. Because the rightmost operand becomes an explicit parameter, there’s no confusion over who is getting modified and who
is getting evaluated.
I don't understand why the left hand operand will always be a class type. If I were overloading +=, for example, why couldn't I overload with the user defined class as the righthand parameter, like below?
void operator+=(int blah, MyNewClass foo);
Thanks in advance!
Despite the comments, you read this correctly: it’s talking about all such modifying operators, and it’s using the statement about the left-hand operand to justify the idea of a member function being “typically preferred”. (If it’s going to be a class-type object, you definitely have the opportunity to use a member function, and we generally prefer to express modifications to such objects in terms of member functions.)
The passage simply doesn’t consider the esoteric possibilities of overloading with non-member functions:
enum nil {};
// Use left-to-right compound assignment:
void operator+=(const int &i,nil &n)
{n=static_cast<nil>(n+i);}
// Make something into a pointer (*):
template<class T>
void* operator*=(T &t,nil) {return &t;}
struct A {operator int();};
// Convert sum to a percentage (%):
double operator%=(A a,A b) {return (a+b)/100.;}
// Infix call notation (like $ in Haskell):
template<class R>
R operator&=(R f(int),A a) {return f(a);}
Very occasionally someone might find a clever way of using, say, >>= in this fashion to emulate Haskell, but for someone just learning the language (to whom that passage is certainly addressed), perhaps the very possibility of such examples is best left unsaid. (Forget I said anything.)
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?
No, you can't overload op.*:
[C++03 & C++11: 13.5/3]: The following operators cannot be overloaded:
. .* :: ?:
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.
You cannot overload .* (see Lightness' answer for standard text), but, interestingly enough, you can overload ->* (similar to how you can overload -> but not .). If that's sufficient for differentiation, then have at it:
struct Int {
int i;
Int operator*(Int rhs) const { return Int{i * rhs.i}; }
Int operator->*(Int rhs) const { return Int{i + rhs.i}; }
friend std::ostream& operator<<(std::ostream& os, Int rhs) {
return os << "Int(" << rhs.i << ')';
}
};
int main() {
Int five{5};
Int six{6};
std::cout << (five * six) << ", " << (five ->* six) << '\n';
}
That'll print Int(30), Int(11).
No, unfortunately you cannot define new operators—you can only overload existing operators (with a few important exceptions, such as operator.). Even then, it's typically only a good idea to overload operators for types which have very clear and uncontroversial existing semantics for a given operator—for instance, any type that behaves as a number is a good candidate for overloading the arithmetic and comparison operators, but you should make sure that operator+ doesn't, say, subtract two numbers.
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?
As for the first part you can overload most of the operators and there are some that you can not overload and the list of operators in C++ are:
Arithmetic
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)
Bitwise
^ (XOR)
| (OR)
& (AND)
~ (Complement)
<< (Shift Left, Insertion to Stream)
>> (Shift Right, Extraction from Stream)
Assignment
= (Assignment)
Relational
== (Equality)
!= (Inequality)
> (Greater-Than)
< (Less-Than)
>= (Greater-Than Or Equal-To)
<= (Less-Than Or Equal-To)
Logical
! (NOT)
&& (AND)
|| (OR)
Compound Assignment
+= (Addition-Assignment)
-= (Subtraction-Assignment)
*= (Multiplication-Assignment)
/= (Division-Assignment)
%= (Modulus-Assignment)
&= (AND-Assignment)
|= (OR-Assignment)
^= (XOR-Assignment)
<<= (Shift-Left Assignment)
>>= (Shift-Right Assignment)
Increment - Decrement - Both have 2 forms (prefix) and (postfix)
++ (Increment)
-- (Decrement)
Subscript
[] (Subscript)
Function Call
() (Function Call)
Address, Reference, Pointer
operator&()
operator*()
operator->()
Comma
operator,()
Member Reference
operator->()
operator->*()
Memory Management
new
delete
new[]
delete[]
Conversion
operator "type" () const
NON Modifiable Operators - Operators that can not be overloaded
?: (Conditional - Ternary)
. (Member Selection)
.* (Member Selection With Pointer To Member)
:: (Scope Resolution)
sizeof() (Object Size Information)
typeid() (Object Type Information)
So knowing this list will help to answer your questions. Can you Create a "New Operator" in C++? No! If you want to implement similar operations in C++; how can I do that?
You have 4 choices: Either overload an already existing operator that can be overloaded, write a function or method to do the type of calculations you want to perform, create a template type to do the work for you, or the last one which is the least common to do but you can also write macros to do them for you.
There is a header only Math API Library that is used quite frequently with OpenGL graphics API and OpenGL's Shader Language GLSL and this library has many features that work with vectors, matrices, quaternions etc., and all the necessary functions and operations that can be done to them. Here is the link to GLM You can have a look at their documentation as well as their library implementations since it is a headers only library or API. This should give you some insight on how they constructed their Vector and Matrix objects and the operations that can be done to them.
BTW: I am seeking to answer the parts of this question as asked. I am also not seeking to replicate all the information in other worthy answers. The bounty seeks something different to the question as asked, so I am not responding to that.
It is actually fairly simple to provide a matrix multiplication. Since I'm not proposing to describe data structures to represent a matrix and fully implement operations and validity checks on them, I'll just provide skeletons to illustrate.
Example 1: operator*() as a member function
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const;
};
M M::operator*(const M &rhs) const
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = a*b; // this relies on M having appropriate constructor(s) to copy or move the result of a*b into c
M d;
d = a * b; // this relies on M having appropriate operator=() to assign d to the result of a*b
}
The above implements operator*() as a member function. So, functionally, c = a*b is equivalent to c = a.operator*(b). The const qualifiers represent the fact that a matrix multiplication a*b does not generally change a or b.
Example 2: operator*() as a non-member function
Now, operator*() can also be implemented as a non-member (optionally a friend), with a skeleton that looks like
class M // our basic matrix class, different operator *
{
public:
// assume other constructors and members to set things up
friend M operator*(const M &lhs, const M &rhs);
};
M operator*(const M &lhs, const M &rhs)
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
// same main() as before
Note that, in this case, a*b is now equivalent to operator*(a, b).
If you want to use both forms, care is needed to avoid ambiguity. If both forms of operator*() are provided they are both valid matches in a statement like c = a*b and the compiler has no means to choose one form over the other. The result is code not compiling.
Example 3: overloading operator*()
It is also possible to overload operator*() - for example, to multiply a matrix by a scalar.
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const; // as in first example
M operator*(double scalar) const; // member form
friend M operator*(double scalar, const M &rhs); // non-member form
};
M M::operator*(double scalar) const
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
M operator*(double scalar, const M &m)
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = b * 2.0; // uses the member form of operator*() above
M d;
d = 2.0*a; // uses the non-member form of operator*() above
}
In the above b*2.0 amounts to a call of b.operator*(2.0) and 2.0*a to a call of the non-member operator*(2.0, a). The member forms can only generally be used in expressions where the left hand operand is of type M. So 2.0*a will not work if only member forms of operator*() is provided.
Discussion
Apart from concerns of ambiguity above, there are other things to be aware of when overloading operators.
It is not possible to change precedence or associativity of operators from their specification in language rules. So, in the expression a+b*c, the * will always have higher precedence than the +. This is also the reason it is not a good idea to overload ^ for exponentiation in C++, since ^ has a lower precedence than + in C++ (being a bitwise operation on integral types). So a + b^c is actually equivalent in C++ to (a + b)^c, not to a + (b^c) (which anyone with basic knowledge of algebra would expect).
The language specifies a set of operators, and it is not possible to create new ones. For example, there is no ** in C++, such that a ** b raises a to the power of b (which other languages can do), and it is not possible to create one.
Not all operators can be overloaded.
One of the operators that cannot be overloaded in C++ is .*. So it is not possible to use such an operator like you would in Matlab. I would generally suggest NOT trying to get the same effect using other operators, because the above constraints will affect that (and cause expressions to give counter-intuitive behaviour). Instead simply provide another named function to do the job. For example, as a member function
class M
{
public:
// other stuff
M ElementWiseProduct(const M &) const;
};
Most of the answers have already covered which operators are and are not overloadable, but none have discussed WHY some are mutable and some aren't.
The following is a quote from Bjarne Stroustrup (the guy who wrote c++) that I found in this stackoverflow answer. Pay particular attention to the third paragraph.
When I decided to allow overloading of operator ->, I naturally considered whether operator . could be similarly overloaded.
At the time, I considered the following arguments conclusive: If obj is a class object then obj.m has a meaning for every member m of that object's class. We try not to make the language mutable by redefining built-in operations (though that rule is violated for = out of dire need, and for unary &).
If we allowed overloading of . for a class X, we would be unable to access members of X by normal means; we would have to use a pointer and ->, but -> and & might also have been re-defined. I wanted an extensible language, not a mutable one.
These arguments are weighty, but not conclusive. In particular, in 1990 Jim Adcock proposed to allow overloading of operator . exactly the way operator -> is.
A page on his website adds a little more:
Can I define my own operators?
Sorry, no. The possibility has been considered several times, but each time I/we decided that the likely problems outweighed the likely benefits.
It's not a language-technical problem. Even when I first considerd it in 1983, I knew how it could be implemented. However, my experience has been that when we go beyond the most trivial examples people seem to have subtlely different opinions of "the obvious" meaning of uses of an operator. A classical example is a ** b ** c. Assume that ** has been made to mean exponentiation. Now should a ** b ** c mean (a ** b) ** c or a ** (b ** c)? I thought the answer was obvious and my friends agreed - and then we found that we didn't agree on which resolution was the obvious one. My conjecture is that such problems would lead to subtle bugs.
So, while most operators can be overloaded, it was never intended for people to create arbitrary operators in c++.
It's as simple (and as difficult!) as defining a function named (in this case) operator*():
Matrix operator*(const Matrix &m1, const Matrix &m2) ...
where Matrix is a class you've defined to represent matrices.
As other answers say, overloading operator.* is not possible.
But I got a good solution for your question, check here.
You can provide any methods in operator-ish form like:
M <matrix_mul> N
Was the unary + operator only included for symmetry with the unary - operator, or does it find some practical use in C++ code?
Searching here, I came across What is the purpose of the unary '+' operator in C?, but the only useful scenarios there involve preprocessor macros. Those are good to know, but they seem to be some less common situations, and involve macros. Are there any use cases involving more common C++ code?
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';
The first insertion writes the character a to cout. The second insertion writes the numeric value of ch to cout. But that's a bit obscure; it relies on the compiler applying integral promotions for the + operator.
Symmetry with unary - isn't entirely useless; it can be used for emphasis:
const int foo = -1;
const int bar = +1;
And an overloaded unary + can be used to denote an operation that yields the same logical value as its operand, while performing some non-trivial computation. (I've seen this done for type conversions in Ada, which permits unary +, but not conversions, to be overloaded.) I don't have a good C++ example to hand, and one could argue that it would be poor style. (Then again, I've seen plenty of rants about overloading <<.)
As for why C++ has it, it's probably largely for consistency with C, which added it with the 1989 ANSI standard. The C Rationale just says:
Unary plus was adopted by the C89 Committee from several
implementations, for symmetry with unary minus.
If you explicitly stay clear of any number value semantics for a class, any operator overloading is clear not to "do as the ints do". In that case, the unary plus may get any meaning, doing much more than just returning *this
Prominent example: Boost.Spirit's unary plus for the embedded EBNF's Kleene Plus generates a parser rule that lets it's argument (a parser rule as well) match one or more times.
The unary + operator turns a lvalue into an rvalue:
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
Oh noes! This code won't link, because someone forgot to define (as well as declare) A::value. std::min takes its arguments by reference so A::value must have an address so a reference can bind to it (technically, the one definition rule says it must be defined exactly once in the program.)
Nevermind, unary plus to the rescue:
int x = std::min(0, +A::value);
The unary plus creates a temporary with the same value, and the reference binds to the temporary, so we can work around the missing definition.
This isn't something you need often, but it is a practical use of the unary plus operator.
Unary + applies integral promotions. #PeteBecker's answer shows one way that can be useful.
For another, note that an unscoped enumeration type gets promoted to an integer type which can represent all values in the enum. So in C++03, even without C++11's std::underlying_type<T>, you could do:
enum MyBitMask {
Flag1 = 0x1,
Flag2 = 0x2,
Flag3 = 0x4,
Flag4 = 0x8000000
};
inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
return static_cast<MyBitMask>( +x & +y );
}
inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
return static_cast<MyBitMask>( +x | +y );
}
Among other things, + converts lambdas to function pointers. Normally the conversion happens automatically, but sometimes it doesn't.
For example, this doesn't compile:
std::array arr{
[](int x){return x*x;},
[](int x){return x*x*x;},
};
You could make it work by specifying the function pointer type as the std::array template parameter, or you could just do this:
std::array arr{
+[](int x){return x*x;},
+[](int x){return x*x*x;},
};
A bit late, but here's a very twisted use that I stumbled across. Apparently the + operator can be useful (if perhaps not strictly necessary) when designing safeguards around the possibility of encountering empty preprocessor tokens. See this post for a more in-depth discussion.
It's practical, but by no means pleasant.
Since for arithmetic variables operator+ generates a new value.
I use it to generate value copies of reference-like (proxy) types.
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
Another option is to use operator* but then the ref_of can be confused with a pointer-like object.
Since for arithmetic variables operator+ generates a new value,
I use it in general to generate value copies of reference-like (proxy) types.
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
...
ref_of<T> r = t;
auto s = +r; // this forces a copy
Another option is to use operator* but then the ref_of can be confused with a pointer-like object.
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?
No, you can't overload op.*:
[C++03 & C++11: 13.5/3]: The following operators cannot be overloaded:
. .* :: ?:
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.
You cannot overload .* (see Lightness' answer for standard text), but, interestingly enough, you can overload ->* (similar to how you can overload -> but not .). If that's sufficient for differentiation, then have at it:
struct Int {
int i;
Int operator*(Int rhs) const { return Int{i * rhs.i}; }
Int operator->*(Int rhs) const { return Int{i + rhs.i}; }
friend std::ostream& operator<<(std::ostream& os, Int rhs) {
return os << "Int(" << rhs.i << ')';
}
};
int main() {
Int five{5};
Int six{6};
std::cout << (five * six) << ", " << (five ->* six) << '\n';
}
That'll print Int(30), Int(11).
No, unfortunately you cannot define new operators—you can only overload existing operators (with a few important exceptions, such as operator.). Even then, it's typically only a good idea to overload operators for types which have very clear and uncontroversial existing semantics for a given operator—for instance, any type that behaves as a number is a good candidate for overloading the arithmetic and comparison operators, but you should make sure that operator+ doesn't, say, subtract two numbers.
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?
As for the first part you can overload most of the operators and there are some that you can not overload and the list of operators in C++ are:
Arithmetic
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)
Bitwise
^ (XOR)
| (OR)
& (AND)
~ (Complement)
<< (Shift Left, Insertion to Stream)
>> (Shift Right, Extraction from Stream)
Assignment
= (Assignment)
Relational
== (Equality)
!= (Inequality)
> (Greater-Than)
< (Less-Than)
>= (Greater-Than Or Equal-To)
<= (Less-Than Or Equal-To)
Logical
! (NOT)
&& (AND)
|| (OR)
Compound Assignment
+= (Addition-Assignment)
-= (Subtraction-Assignment)
*= (Multiplication-Assignment)
/= (Division-Assignment)
%= (Modulus-Assignment)
&= (AND-Assignment)
|= (OR-Assignment)
^= (XOR-Assignment)
<<= (Shift-Left Assignment)
>>= (Shift-Right Assignment)
Increment - Decrement - Both have 2 forms (prefix) and (postfix)
++ (Increment)
-- (Decrement)
Subscript
[] (Subscript)
Function Call
() (Function Call)
Address, Reference, Pointer
operator&()
operator*()
operator->()
Comma
operator,()
Member Reference
operator->()
operator->*()
Memory Management
new
delete
new[]
delete[]
Conversion
operator "type" () const
NON Modifiable Operators - Operators that can not be overloaded
?: (Conditional - Ternary)
. (Member Selection)
.* (Member Selection With Pointer To Member)
:: (Scope Resolution)
sizeof() (Object Size Information)
typeid() (Object Type Information)
So knowing this list will help to answer your questions. Can you Create a "New Operator" in C++? No! If you want to implement similar operations in C++; how can I do that?
You have 4 choices: Either overload an already existing operator that can be overloaded, write a function or method to do the type of calculations you want to perform, create a template type to do the work for you, or the last one which is the least common to do but you can also write macros to do them for you.
There is a header only Math API Library that is used quite frequently with OpenGL graphics API and OpenGL's Shader Language GLSL and this library has many features that work with vectors, matrices, quaternions etc., and all the necessary functions and operations that can be done to them. Here is the link to GLM You can have a look at their documentation as well as their library implementations since it is a headers only library or API. This should give you some insight on how they constructed their Vector and Matrix objects and the operations that can be done to them.
BTW: I am seeking to answer the parts of this question as asked. I am also not seeking to replicate all the information in other worthy answers. The bounty seeks something different to the question as asked, so I am not responding to that.
It is actually fairly simple to provide a matrix multiplication. Since I'm not proposing to describe data structures to represent a matrix and fully implement operations and validity checks on them, I'll just provide skeletons to illustrate.
Example 1: operator*() as a member function
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const;
};
M M::operator*(const M &rhs) const
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = a*b; // this relies on M having appropriate constructor(s) to copy or move the result of a*b into c
M d;
d = a * b; // this relies on M having appropriate operator=() to assign d to the result of a*b
}
The above implements operator*() as a member function. So, functionally, c = a*b is equivalent to c = a.operator*(b). The const qualifiers represent the fact that a matrix multiplication a*b does not generally change a or b.
Example 2: operator*() as a non-member function
Now, operator*() can also be implemented as a non-member (optionally a friend), with a skeleton that looks like
class M // our basic matrix class, different operator *
{
public:
// assume other constructors and members to set things up
friend M operator*(const M &lhs, const M &rhs);
};
M operator*(const M &lhs, const M &rhs)
{
// implement checks on dimensions, throw an exception if invalid
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
// same main() as before
Note that, in this case, a*b is now equivalent to operator*(a, b).
If you want to use both forms, care is needed to avoid ambiguity. If both forms of operator*() are provided they are both valid matches in a statement like c = a*b and the compiler has no means to choose one form over the other. The result is code not compiling.
Example 3: overloading operator*()
It is also possible to overload operator*() - for example, to multiply a matrix by a scalar.
class M // a basic matrix class
{
public:
// assume other constructors and members to set things up
M operator*(const M &rhs) const; // as in first example
M operator*(double scalar) const; // member form
friend M operator*(double scalar, const M &rhs); // non-member form
};
M M::operator*(double scalar) const
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
M operator*(double scalar, const M &m)
{
M result;
// implement the multiplication (typical iterations) and store results in result
return result;
}
int main()
{
M a;
M b;
// set up elements of a and b as needed
M c = b * 2.0; // uses the member form of operator*() above
M d;
d = 2.0*a; // uses the non-member form of operator*() above
}
In the above b*2.0 amounts to a call of b.operator*(2.0) and 2.0*a to a call of the non-member operator*(2.0, a). The member forms can only generally be used in expressions where the left hand operand is of type M. So 2.0*a will not work if only member forms of operator*() is provided.
Discussion
Apart from concerns of ambiguity above, there are other things to be aware of when overloading operators.
It is not possible to change precedence or associativity of operators from their specification in language rules. So, in the expression a+b*c, the * will always have higher precedence than the +. This is also the reason it is not a good idea to overload ^ for exponentiation in C++, since ^ has a lower precedence than + in C++ (being a bitwise operation on integral types). So a + b^c is actually equivalent in C++ to (a + b)^c, not to a + (b^c) (which anyone with basic knowledge of algebra would expect).
The language specifies a set of operators, and it is not possible to create new ones. For example, there is no ** in C++, such that a ** b raises a to the power of b (which other languages can do), and it is not possible to create one.
Not all operators can be overloaded.
One of the operators that cannot be overloaded in C++ is .*. So it is not possible to use such an operator like you would in Matlab. I would generally suggest NOT trying to get the same effect using other operators, because the above constraints will affect that (and cause expressions to give counter-intuitive behaviour). Instead simply provide another named function to do the job. For example, as a member function
class M
{
public:
// other stuff
M ElementWiseProduct(const M &) const;
};
Most of the answers have already covered which operators are and are not overloadable, but none have discussed WHY some are mutable and some aren't.
The following is a quote from Bjarne Stroustrup (the guy who wrote c++) that I found in this stackoverflow answer. Pay particular attention to the third paragraph.
When I decided to allow overloading of operator ->, I naturally considered whether operator . could be similarly overloaded.
At the time, I considered the following arguments conclusive: If obj is a class object then obj.m has a meaning for every member m of that object's class. We try not to make the language mutable by redefining built-in operations (though that rule is violated for = out of dire need, and for unary &).
If we allowed overloading of . for a class X, we would be unable to access members of X by normal means; we would have to use a pointer and ->, but -> and & might also have been re-defined. I wanted an extensible language, not a mutable one.
These arguments are weighty, but not conclusive. In particular, in 1990 Jim Adcock proposed to allow overloading of operator . exactly the way operator -> is.
A page on his website adds a little more:
Can I define my own operators?
Sorry, no. The possibility has been considered several times, but each time I/we decided that the likely problems outweighed the likely benefits.
It's not a language-technical problem. Even when I first considerd it in 1983, I knew how it could be implemented. However, my experience has been that when we go beyond the most trivial examples people seem to have subtlely different opinions of "the obvious" meaning of uses of an operator. A classical example is a ** b ** c. Assume that ** has been made to mean exponentiation. Now should a ** b ** c mean (a ** b) ** c or a ** (b ** c)? I thought the answer was obvious and my friends agreed - and then we found that we didn't agree on which resolution was the obvious one. My conjecture is that such problems would lead to subtle bugs.
So, while most operators can be overloaded, it was never intended for people to create arbitrary operators in c++.
It's as simple (and as difficult!) as defining a function named (in this case) operator*():
Matrix operator*(const Matrix &m1, const Matrix &m2) ...
where Matrix is a class you've defined to represent matrices.
As other answers say, overloading operator.* is not possible.
But I got a good solution for your question, check here.
You can provide any methods in operator-ish form like:
M <matrix_mul> N
I've been looking for an example that shows how to implement constraints in C++ (or a boost library that lets me do this easily), but without much luck. The best I could come up with off the top of my head is:
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
template<typename T>
class constrained
{
public:
constrained(boost::function<bool (T)> constraint, T defaultValue, T value = defaultValue)
{
ASSERT(constraint(defaultValue));
ASSERT(constraint(value));
this->value = value;
this->defaultValue = defaultValue;
this->constraint = constraint;
}
void operator=(const T &assignedValue)
{
if(constraint(assignedValue))
value = assignedValue;
}
private:
T value;
T defaultValue;
boost::function<bool (T)> constraint;
};
int main(int argc, char* argv[])
{
constrained<int> foo(boost::lambda::_1 > 0 && boost::lambda::_1 < 100, 5, 10);
foo = 20; // works
foo = -20; // fails
return 0;
}
Of course there's probably some more functionality you'd want from a constraint class. This is just an idea for a starting point.
Anyway, the problem I see is that I have to overload all operators that T defines in order to make it really behave like a T, and there is no way for me to find out what those are. Now, I don't actually need constraints for that many different types, so I could just leave out the template and hard code them. Still, I'm wondering if there's a general (or at least more succint/elegant) solution or if there's anything seriously wrong with my approach.
Looks good as for tiny example. But be sure to implement all the operators and handle somehow wrong values.
foo = 100; // works
++foo; // should throw an exception or perform an assert
Use boost operators to help you with operators overload.
And probably it would be good to have an option as a template parameter: either exception or assertion.
I'd use such class. It is always better to have an index parameter that auto check vector range and do assertion.
void foo( VectorIndex i );
You don't need to overload all operators as others have suggested, though this is the approach that offers maximum control because expressions involving objects of type constrained<T> will remain of this type.
The alternative is to only overload the mutating operators (=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, pre and post ++, pre and post --) and provide a user-defined conversion to T:
template<typename T>
class constrained {
... // As before, plus overloads for all mutating operators
public:
operator T() const {
return value;
}
};
This way, any expression involving a constrained<T> object (e.g. x + y where x is int and y is constrained<int>) will be an rvalue of type T, which is usually more convenient and efficient. No safety is lost, because you don't need to control the value of any expression involving a constrained<T> object -- you only need to check the constraints at a time when a T becomes a constrained<T>, namely in constrained<T>'s constructor and in any of the mutating operators.
Boost.Constrained_Value may be of interest to you. It was reviewed last December, but it is not in the latest Boost release. IIRC, the review was mostly positive, but the decision is still pending.
I agree with Mykola Golubyev that boost operators would help.
You should define all the operators that you require for all the types you are using.
If any of the types you are using don't support the operator (for example the operator++()), then code that calls this method will not compile but all other usages will.
If you want to use different implementations for different types then use template specialisation.
I might just be confused, but if you are facing parameters that must not violate specific constraints, wouldn't it be easiest to create a class for them, checking for constraints in constructors and assignment operators?
Boost actually had such a library under discussion (I don't know what became of it). I've also written my own version of such a type, with slightly different behaviour (less flexible, but simpler). I've blogged an admittedly somewhat biased comparison here: Constrained vs. restricted value types
Edit: apparently Eric knows better what happened to boost's implementation.