Asked  7 Months ago    Answers:  5   Viewed   32 times

Specifically, I would like to create an Array class and would like to overload the [] operator.

 Answers

39

If you are using PHP5 (and you should be), take a look at the SPL ArrayObject classes. The documentation isn't too good, but I think if you extend ArrayObject, you'd have your "fake" array.

EDIT: Here's my quick example; I'm afraid I don't have a valuable use case though:

class a extends ArrayObject {
    public function offsetSet($i, $v) {
        echo 'appending ' . $v;
        parent::offsetSet($i, $v);
    }
}

$a = new a;
$a[] = 1;
Wednesday, March 31, 2021
 
Lloydworth
answered 7 Months ago
39

It is in fact possible to create new operators or overload existing ones for built-in data types in MATLAB. I describe one example of this in my answer to another SO question about modifying the default overflow behavior of integer types.

First, you may want to look at what methods currently exist for cell arrays. You can do this using the function METHODS, and here's what I get in MATLAB R2010b:

>> methods cell

Methods for class cell:

aa2nt            issorted         regexptranslate  strfind          
accumarray       newdepfun        reshape          strjust          
cell2struct      nt2aa            rna2dna          strmatch         
ctranspose       nwalign          seq2regexp       strtok           
display          permute          setdiff          transpose        
dna2rna          regexp           setxor           union            
intersect        regexpi          sort             unique           
ismember         regexprep        strcat           

The arithmetic operator methods would show up in the above list as their function equivalents, like plus for the + operator or times for the .* operator. Only the transpose method (.' operator) is defined for cell arrays. You would have to create the rest yourself, defining how a given operator will behave for cell arrays arguments.

You can do this by first making a new folder called @cell and placing it in an existing folder on your MATLAB path. You would then place your new methods in the @cell folder. For example, a very simple implementation of a plus method for cell arrays (without any input-checking, error-checking, etc.) would be this:

function C = plus(A,B)
  C = cellfun(@plus,A,B,'UniformOutput',false);  %# Apply plus cell-wise
end

In the above code, you would probably first want to check that the operands A and B are cell arrays of the same size. However, you could create whatever unique functionality you want, such as allowing B to be a scalar value which would get added to every cell of A. It's totally up to you to define how the + operator will behave for cell arrays.

This would then allow you to write your code in a much more compact way, as in this example:

>> A = {[1 2 3] [4 5] 6};  %# One 3-element cell array
>> B = {5 [4 5] 2};        %# Another 3-element cell array
>> C = A+B;                %# Use the new plus operator
>> C{:}                    %# Display the cell contents

ans =

     6     7     8

ans =

     8    10

ans =

     8

I can't really speak to the behind-the-scenes optimizations and how this might affect them. I know that the documentation "Techniques for Improving Performance" specifically mentions this about overloading built-in functions:

Overloading MATLAB built-in functions on any of the standard MATLAB data classes can negatively affect performance. For example, if you overload the plus function to handle any of the integer classes differently, you may hinder certain optimizations in the MATLAB built-in function code for plus, and thus may slow down any programs that make use of this overload.

However, in your case you aren't overloading existing functions for a class. You're simply creating new ones that didn't exist for that class, so it's hard to say what effect this may ultimately have on performance.

Sunday, June 13, 2021
 
dkcwd
answered 5 Months ago
70

No, it is not possible. C does not support operator overloading by the developer.

Friday, July 30, 2021
 
eliotlencelot
answered 3 Months ago
70

If you overload a binary operator as a member function, it ends up asymmetrical: the left operand must be the exact type for which the operator is overloaded, but the right operand can be anything that can be converted to the correct type.

If you overload the operator with a non-member function, then both operands can be converted to get the correct type.

What you have as your second point looks like a concrete example of the same point, not really anything separate at all. Here's a concrete example of what I'm talking about:

class Integer {
    int val;
public:
    Integer(int i) : val(i) {}
    operator int() { return val; }

    // Integer operator+(Integer const &other) const { return Integer(val + other.val); }

    friend Integer operator+(Integer const &a, Integer const &b) { 
        return Integer(a.val + b.val);
    }
};


int main() { 
    Integer x(1);

    Integer y = x + 2; // works with either operator overload because x is already an Integer

    Integer z = 2 + x; // works with global overload, but not member overload because 2 isn't an Integer, but can be converted to an Integer.
    return 0;
}

Also note that even though the definition of the friend function is inside the class definition for Integer, the fact that it's declared as a friend means it's not a member function -- declaring it as friend makes it a global function, not a member.

Bottom line: such overloads should usually be done as free functions, not member functions. Providing the user with an operator that works correctly (drastically) outweighs theoretical considerations like "more object oriented". When necessary, such as when the implementation of the operator needs to be virtual, you can do a two-step version, where you provide a (possibly virtual) member function that does the real work, but the overload itself is a free function that invokes that member function on its left operand. One fairly common example of this is overloading operator<< for a hierarchy:

class base { 
    int x;
public:
    std::ostream &write(std::ostream &os) const { 
        return os << x;
    }
};

class derived : public base { 
    int y;
public:
    std::ostream &write(std::ostream &os) const { 
        return (base::write(os) << y);
    }
};

std::ostream &operator<<(std::ostream &os, base const &b) {
    return b.write(os);
}

This supports both polymorphic implementation (and access to a base class' protected members, if necessary) without giving up the normal characteristics of the operator to get it.

The primary exceptions to overloading binary operators as free functions are assignment operators (operator=, operator+=, operator-=, operator*= and so on). A conversion would produce a temporary object, which you can't assign to anyway, so for this particular case, the overload should be (must be, as a matter of fact) a member function instead.

Saturday, August 7, 2021
 
Nil
answered 3 Months ago
Nil
94

I wouldn't overload operator&& or operator||. Even if you define a class that gives rise to a Boolean algebra (finite sets, for example), it would probably be a better choice to overload operator& and operator|.

The reason is that C++ programmers expect special semantics for operator&& and operator||: they are short-circuited, i.e. don't evaluate their right-hand argument if not necessary. You can't get this behavior by overloading, since you'll be defining a function.

Overloading operator, has been done in e.g. the Boost.Assign library. This is also the only example of its overloading that I know, and I've never even considered overloading it myself. You'd better have a very specific use case for it where no other operator is suited.

Sunday, August 15, 2021
 
pwaring
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share