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.
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.)
(note the original question title had "instead of an rvalue" rather than "instead of a const reference". One of the answers below is in response to the old title. This was fixed for clarity)
One common construct in C and C++ is for chained assignments, e.g.
int j, k;
j = k = 1;
The second = is performed first, with the expression k=1 having the side effect that k is set to 1, while the value of the expression itself is 1.
However, one construct that is legal in C++ (but not in C) is the following, which is valid for all base types:
int j, k=2;
(j=k) = 1;
Here, the expression j=k has the side effect of setting j to 2, and the expression itself becomes a reference to j, which then sets j to 1. As I understand, this is because the expression j=k returns a non-const int&, e.g. generally speaking an lvalue.
This convention is usually also recommended for user-defined types, as explained in "Item 10: Have assignment operators return a (non-const) reference to *this" in Meyers Effective C++(parenthetical addition mine). That section of the book does not attempt to explain why the reference is a non-const one or even note the non-constness in passing.
Of course, this certainly adds functionality, but the statement (j=k) = 1; seems awkward to say the least.
If the convention were to instead have builtin assignment return const references, then custom classes would also use this convention, and the original chained construction allowed in C would still work, without any extraneous copies or moves. For example, the following runs correctly:
#include <iostream>
using std::cout;
struct X{
int k;
X(int k): k(k){}
const X& operator=(const X& x){
// the first const goes against convention
k = x.k;
return *this;
}
};
int main(){
X x(1), y(2), z(3);
x = y = z;
cout << x.k << '\n'; // prints 3
}
with the advantage being that all 3 (C builtins, C++ builtins, and C++ custom types) all are consistent in not allowing idioms like (j=k) = 1.
Was the addition of this idiom between C and C++ intentional? And if so, what type of situation would justify its use? In other words, what non-spurious benefit does does this expansion in functionality ever provide?
By design, one fundamental difference between C and C++ is that C is an lvalue-discarding language and C++ is an lvalue-preserving language.
Before C++98, Bjarne had added references to the language in order to make operator overloading possible. And references, in order to be useful, require that the lvalueness of expressions be preserved rather than discarded.
This idea of preserving the lvalueness wasn't really formalized though until C++98. In the discussions preceding the C++98 standard the fact that references required that the lvalueness of an expression be preserved was noted and formalized and that's when C++ made one major and purposeful break from C and became an lvalue preserving language.
C++ strives to preserve the "lvalueness" of any expression result as long as it is possible. It applies to all built-in operators, and it applies to built-in assignment operator as well. Of course, it is not done to enable writing expressions like (a = b) = c, since their behavior would be undefined (at least under the original C++ standard). But because of this property of C++ you can write code like
int a, b = 42;
int *p = &(a = b);
How useful it is is a different question, but again, this is just one consequence of lvalue-preserving design of C++ expressions.
As for why it is not a const lvalue... Frankly, I don't see why it should be. As any other lvalue-preserving built-in operator in C++ it just preserves whatever type is given to it.
I'll answer the question in the title.
Let's assume that it returned an rvalue reference. It wouldn't be possible to return a reference to a newly assigned object this way (because it's an lvalue). If it's not possible to return a reference to a newly assigned object, one needs to create a copy. That would be terribly inefficient for heavy objects, for instance containers.
Consider an example of a class similar to std::vector.
With the current return type, the assignment works this way (I'm not using templates and copy-and-swap idiom deliberately to keep the code as simple as possible):
class vector {
vector& operator=(const vector& other) {
// Do some heavy internal copying here.
// No copy here: I just effectively return this.
return *this;
}
};
Let's assume that it returned an rvalue:
class vector {
vector operator=(const vector& other) {
// Do some heavy stuff here to update this.
// A copy must happen here again.
return *this;
}
};
You might think about returning an rvalue reference, but that wouldn't work either: you can't just move *this (otherwise, a chain of assignments a = b = c would run b), so a second copy will also be required to return it.
The question in the body of your post is different: returning a const vector& is indeed possible without any of the complications shown above, so it looks more like a convention to me.
Note: the title of the question refers to built-ins, while my answer covers custom classes. I believe that it's about consistency. It would be quite surprising if it acted differently for built-in and custom types.
Built-in operators don't "return" anything, let alone "return a reference".
Expressions are characterized mainly by two things:
their type
their value category.
For example k + 1 has type int and value category "prvalue", but k = 1 has type int and value category "lvalue". An lvalue is an expression that designates a memory location, and the location designated by k = 1 is the same location that was allocated by the declaration int k;.
The C Standard only has value categories "lvalue" and "not lvalue". In C k = 1 has type int and category "not lvalue".
You seem to be suggesting that k = 1 should have type const int and value category lvalue. Perhaps it could, the language would be slightly different. It would outlaw confusing code but perhaps outlaw useful code too. This is a decision that's hard for a language designer or design committee to evaluate because they can't think of every possible way the language could be used.
They err on the side of not introducing restrictions that might turn out to have a problem nobody foresaw yet. A related example is Should implicitly generated assignment operators be & ref-qualified?.
One possible situation that comes to mind is:
void foo(int& x);
int y;
foo(y = 3);
which would set y to 3 and then invoke foo. This wouldn't be possible under your suggestion. Of course you could argue that y = 3; foo(y); is clearer anyway, but that's a slippery slope: perhaps increment operators shouldn't be allowed inside larger expressions etc. etc.
It is easy to introduce new infix operators in C++
// User-defined infix operator framework
template <typename LeftOperand, typename Operation>
struct LeftHelper
{
const LeftOperand& leftOperand;
const Operation& operation;
LeftHelper(const LeftOperand& leftOperand,
const Operation& operation)
: leftOperand(leftOperand), operation(operation) {}
};
template <typename LeftOperand, typename Operation >
auto operator < (const LeftOperand& leftOperand,
Operation& operation)
{
return LeftHelper<LeftOperand, Operation>(leftOperand, operation);
}
template <typename LeftOperand, typename Operation, typename RightOperand>
auto operator > (LeftHelper<LeftOperand, Operation> leftHelper,
const RightOperand& rightOperand)
{
return leftHelper.operation(leftHelper.leftOperand, rightOperand);
}
// Defining a new operator
#include <cmath>
static auto pwr = [](const auto& operand1, const auto& operand2) { return std::pow(operand1, operand2); };
// using it
#include <iostream>
int main()
{
std::cout << (2 <pwr> 16) << std::endl;
return 0;
}
Live demo
Unfortunately, this power operator has wrong precedence and associativity. So my question is: how to fix this? I want my <pow> to have higher precedence than * and associate to the right, just like in the mathematical notation.
Edit It is possible to vary the precedence by using different brackets, e.g. |op|, /op/, *op* or even, if one is so inclined, <<--op-->>, but one cannot go higher than the highest built-in operator precedence this way. But today C++ is so powerful with template metaprogramming and type deduction, there simply ought to be some other way to achieve the desired result.
Additionally, it would be nice if I could use pow and not pwr. Unfortunately in some implementations #include <cmath> brings pow into the global namespace, so there will be a conflict. Can we overload operator not such that a declaration of the form
not using std::pow;
removed std::pow from the global namespace?
Further reading: a related proposal by Bjarne Stroustrup.
The principle of least surprise is important, and it is key that a*b *power* c * d evaluate to a* (b^c) *d. Luckily there is an easy solution.
To ensure that *power* has a higher precedence than multiplication, you have to use a similar named operator technique for multiplication.
Then instead of directly calculating the results of *power* and *times*, you instead build an expression tree. This expression tree, when evaluated, can apply arbitrary precedence rules.
We can do this with every built-in operator, giving us an easy to read syntax that permits compile-time metaprogramming of operator precedence:
auto z =equals= bracket<
a *plus* b *times* c *power* bracket<
a *plus* b
>bracket *power* x *times* y
>bracket;
To avoid this expression template from being stored longer than optimal, simply overload operator auto()&& to return the deduced type. If your compiler fails to support that feature, =equals= can return the proper type at a mild cost of clarity.
Note that the above syntax is actually realizable in C++ using techniques similar to the OP's. An actual implementation is larger than a SO post should contain.
There are other benefits. As everyone knows, obscure ASCII characters in programming languages have fallen out of favor, and people reading C++ may be confuesed by expressions like:
int z = (a + b* pow(c,pow(x,a+b))*y);
With this technique, all operators have readable names that make their meaning clear, and everything is done infix instead of mixing infix and prefix notation.
Similar solutions to ensure that pow is available can be done by reimplementing <cmath> as <cmath_nopow> yourself. This avoids overloading operator not on language constructs, which causes AST grammar monads to decouple, and/or violates the standard. Maybe try Haskell?
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
So I'm in a basic programming II class. We have to create a program that makes 4 different functions that will change the way an operator works. I've looked up multiple examples and sets of text that display how to do this, but I cannot make which way of what any of the code means. To me something like this should work.
int operator++()
{
variableA--;
}
To me, this says if you encounter a ++, then -- from the variable, now obvious it doesn't work like this. All the examples I've found create their own data type. Is there a way to overload an operator using an int or a double?
All the examples create their own data type since this is one of the rules for operator overloading: An overloaded operator must work on at least one user-defined type.
Even if you could overload ++ for integers, the compiler wouldn't know which one to use -- your version or the regular version; it would be ambiguous.
You seem to think of operators as single functions, but each overload is a completely separate function differentiated by its function signature (type and sometimes number of arguments), while having the same operator symbol (this is the definition of "overloading").
So, you can't overload ++ to always do something different; this would really be operator overriding, which C++ doesn't allow.
You can define ++ for a type you've created though:
class MyType {
public:
int value;
};
MyType const& operator++(MyType& m) { // Prefix
++m.value;
return m;
}
const MyType operator++(MyType& m, int) { // Postfix (the 'int' is just to differentiate it from the prefix version)
MyType temp = m;
++m.value;
return temp;
}
int main() {
MyType m;
m.value = 0;
m++; // Not m.value++
cout << m.value; // Prints 1
}
Note that this set of ++ operators was defined outside of the MyType class, but could have been defined inside instead (they would gain access to non-public members that way), though their implementations would be a little different.
You can't overload operators of built-in types. (Well, technically you can overload things like "int + MyClass" - but not when both sides are built-in types)
Take a look at How can I overload the prefix and postfix forms of operators ++ and --?