Overloading function call operator and assignment - c++

In a project of mine, I'm writing a wrapper for std::vector. I'm doing this because I am using homogeneous coordinates and for some operations it's just easier to temporarily 'forget' the fourth coordinate.
Now I stumbled upon a problem. I have loads of assignments like the following:
Vector v;
v(0) = 5;
v(1) = 6;
and so on. I also want to do the following:
double x;
x = v(0);
For that last thing, I can overload the () operator, but how would implement the first thing? (the zero and one being an index).

Just return reference.
class Vector
{
int data[4];
int & operator() (int index) { return data[index]; }
};

Return a non-const reference to the element to be modified.

Two things-
You should probably be overloading operator[] to do this rather than operator(), since it's the more natural operator here. operator() is used to create function objects, while operator[] is the operator meaning "pick out the element at this position."
You can support assignment to the result of operator[] / operator() by having the function return a reference to the value that should be written to. As a simple example, here's some code that represents a class wrapping a raw array:
(code here:)
class Array {
public:
int& operator[] (unsigned index);
int operator[] (unsigned index) const;
private:
int array[137];
};
int& Array::operator[] (unsigned index) {
return array[index];
}
int Array::operator[] (unsigned index) const {
return array[index];
}
The second of these functions is a const overload so you can have const Array read but not write values.

In the standard libraries, such things are implemented by having operator() (well, actually usually operator[]) return type double &. By returning a reference to a double, you can assign to or from it.
However, are you sure you want to wrap this around std::vector? This class is not a vector in the mathematical sense; it's much like a Java ArrayList, and so not at all efficient for small structures. Usually when I'm writing my own vector classes I'm planning on having lots of them around, so I implement a class from scratch on top of a static array.

Related

Overload operator* without allocating new memory

I have class foo that manages a vector of floats of fixed length and some metadata. I have implemented a naive overload for operator*:
constexpr int numOfElements = 9;
class foo {
public:
foo()
: x(0), y(0), data(numOfElements)
{}
foo operator*(float value) {
foo result;
for (size_t k = 0; k < this->data.size(); ++k)
result.data[k] = this->data[k] * value;
return result;
}
int x;
int y;
std::vector<float> data;
};
later, I use it in the following way:
some_foo = *ptr_to_another_foo * 5;
where some_foo and ptr_to_another_foo were defined elsewhere and hold some values. This computes the correct result. However, result foo in the overloaded operator creates another object which causes memory allocation which is unacceptable due to performance reasons. Since some_foo already has memory allocated for data, is there a way to implement the overloaded operator in such a way that some_foo.datas memory will be used instead of allocating the temporary foo result?
I could always implement a C-like pointer-based multiplication function, but I would like to do something more idiomatic in C++.
Write a operator*= that multiplies the elements in place:
foo& operator*=(float value) {
for (size_t k = 0; k < this->data.size(); ++k)
this->data[k] *= value;
return *this;
}
If later you realize that you do need also operator* you can implement it in terms of operator*=:
foo operator*(float value) const {
foo result = *this;
result *= value;
return result;
}
Note that operator* is expected to return a new object and not modify this (it should be a const method), while operator*= is expected to return a reference to *this (after modifying it). If you want to make the operation in place, better use the compound *=.
Do not return a foo. Instead, return a wrapper object which refers to *this and can be used as operand for assignment into another foo, changing its state with the multiplied values. This has the caveat that the returned wrapper becomes invalid in case the referred foo is destroyed.
A general pattern for this idea is called expression templates. This is commonly used in linear algebra libraries.

How to define []= and at() = for a custom collection?

EDIT: This question is not for overriding the operator [] I know how to do that
I have implemented My own collection class, and for assigning data I would like to provide the same operators/functions as std::vector.
However, I have not been able to find a way to define the operators [index]=elm and at(index) = elm.
I am not even completely sure what to terms to search for as these two are not exactly operators
Define your operator[] overload and your at function to return a reference to the specified item. You can then assign the new value through that reference.
There is no []= operator. If your operator[] function returns a reference that can be assigned to, that's all you need.
Simple example to demonstrate the idea.
struct Foo
{
int i;
int& operator[](int) { return i; };
int operator[](int) const { return i; };
}
Now you can use
Foo f;
f[10] = 20; // The index is not used by Foo::operator[]
// This is just to demonstrate the syntax.
You need to do the same with the at() function.

About using returned references

I'm having some trouble trying to understand proper usage of returned references in C++.
I have a class with a "big" object inside. I want to be able to use this object outside the class "read only" mode by returning a const reference to it.
The problem is I don't quite understand when objects get copied and when they don't.
Most of the questions about returning references where about returning objects allocating on the stack, which is not my particular problem, so I've prepared this little example:
class foo {
int a;
public:
foo() {
a = 3;
}
int& getInt() {
return a;
}
const int& useInt() {
return a;
}
void print() {
cout << "Inside class: a = " << a << endl;
}
};
int main() {
foo foo1;
int& goodRef = foo1.getInt();
int badRef = foo1.getInt();
goodRef = 4;
badRef = 5;
foo1.print();
foo1.getInt() = 6;
foo1.print();
int usingIt = 10*foo1.useInt();
}
What I understand is:
In int& goodRef = foo1.getInt(); nothing is copied, only the class owned a exists.
In int badRef = foo1.getInt(); badRef is a copy of a, so there are 2 separate objects, a and badRef.
So depending on what type of object catches the return value it is copied or it is not, so my question is:
When I use the reference like in int usingIt = 10*foo1.useInt(); is it copied and then used to multiply or only the value inside the class is used?
In this example it doesn't matter since it is only an int, but if it was a big object it would be a big deal.
Thanks!
Edit: Thanks to all the answers, but I get that having such methods inside a class is bad, I only put them for the sake of the example.
My actual class has a bunch of objects inside and an interface and bla bla, but one particular object is a glm::mat4. What i want is to be able to write something like glm::vec4 finalVec = foo1.getMatrix() * vec. But I dont want the whole matrix to be copied and then multiplied, rather I want to use the matrix that is already inside my class to perform the multiplication and at the same time not let the user modify it. I supposed something similar to useInt but with the mat4 would work but I wasn't sure and that's why I asked the question.
The glm specificatioon is very confuse for me, but I think the operator * is described as:
glm::mat4 operator* (glm::mat4 const & m, glm::vec4 const & v);
In your example int usingIt = 10*foo1.useInt();, the operator*(), depending on it's argument signature and internals, could cause a copy of your object to take place, at which point it would then be assigned (rather than copied again) into the value of usingIt. If your object was an aggregate or class object type, the copy using the object type's assignment operator would typically be elided using a compiler optimization step.
In general, anytime you are copying a l-value reference type (i.e., T& or const T&) to an aggregate or class object to a non-reference type (i.e., type T), a copy constructor, constructor, assignment operator, or conversion operator is invoked on the returned reference to the object.
If getInt returns int& why are you catching the return value in an int? What do you expect, that the compiler changes your source code to use a reference to int? It can't do anything else than copying the value of the object pointed by the reference.
On the other hand I think you have a bad example. Either you define a single method that returns a const reference:
int const & getInt() { return a; }
Or you provide two methods, one const and one non const:
int& getInt() { return a; }
int const & getInt() const { return a; }
Having both getInt and useInt does not stop anyone from using getInt and actually changing the value of the object in an way that is not intended.
When you use const reference you can only use const methods of this object. E.g. when you have STL vector you can get size, but you can't push_back elements to it.
vector<int> a;
vector<int> &c = a;
const vector<int> &b = a;
a.size();
b.size();
a.push_back(4);
c.push_back(4);
//our vector is now 4 4
//b.push_back(4); compilation error
In C++ you copy when you want to copy: for example
Function which copies:
int x(vector<int> b)
Function which doesn't copy:
int x(vector<int> &b)
You can read more here

Is this the proper way to overload[] with a composed vector class

I am building a custom vector class with an std::vector as its sole member, and adding a variety of math functions to it by overloading +,- and others.
I am doing this for direct accessing vector elements:
template <typename T, int N>
class Vector{
std::vector<T> v;
public:
Vector():v(N,0){}
const T& operator[](int i)const{
return v.at(i);
}
T& operator[](int i){
return v.at(i);
}
Is this an acceptable technique for overloading in this case, such that I can read an element from a const Vector<...> as well as assign to an element from a non-const? Since at returns a reference, one could assign to an element correctly in this case?
Yes, that's a perfectly reasonable use of overloading. I question the use of at, however. It would be better to have both at and operator[], which pass through to their std::vector counterparts. This way, you give the caller the choice between safety and performance (which is why the two versions exist in the first place).

Accessing vector in class

If I have a vector as a private member in my class, what's the best way to access it? For example, take the following simple class
class MCL{
private:
std::vector my_vec;
public:
// Include constructor here and other member functions
}
What's the best way to access my_vec? Specifically, I would like to use a getter function to access it.
return it by const reference, or just by reference if you want to allow changing.
const std::vector<T> & getVector() const
{
return vector;
}
usage:
const std::vector<T> &v = myClass.getVector();
Create a public function called
std:vector getMyVec() {return my_vec;}
Depending on the semantics of your class, you may want to implement operator[]:
T& operator[](int i) {
return my_vec[i];
}
This way you can user [] to access the contents of your vector:
MCL a;
a[0] = 3;
std::cout << a[0] << std::endl;
Note that this may be considered abuse of operator[] or bad practice, but it is up to the developer to judge if this construct fits in the class, depending on its semantics.
Also note that this solution does not provides a way to insert or delete elements from the vector, just access to the elements already there. You may want to add other methods to do these or to implement something like:
T& operator[](int i) {
if(my_vec.size() < i)
my_vec.resize(i+1);
return my_vec[i];
}
Again, it is up to the semantics of your class and your usage pattern of it. This may or may not be a good idea.