Hi I came across this piece of code. It demonstrates how to work with matrix structures of the dlib library.
According to this one can initialize a matrix structure by:
M = 54.2, 7.4, 12.1,
1, 2, 3,
5.9, 0.05, 1;
How can this be possible in C++?
Is this some kind of operator overloading?
This is possible by overloading operator,
(operator comma), and for example make it push new floating point values into M
.
A thing to notice is that operator,
should always have at least one parameter of class type, therefore you'll have to create a class that is implicitly convertible to floating point value (for example via a non explicit
constructor with 1 argument of type double
or float
).
For example we'll try to do this for a wrapper type over an std::vector
and we'll try to make M = 1, 2, 3, 4, 5
a valid expression which results in an std::vector
with those elements in sequence. You'll see that this is easily applicable to the matrix example you gave.
A thing to remember is that operator=
has more precedence over operator,
(as shown in this table of operator precedence); therefore M = 1, 2, 3, 4, 5
will really be parsed as: (((((M = 1), 2), 3), 4), 5)
.
Given that, we'll start by creating our class container
with an operator=
that takes a single value and pushes it into the container:
template<typename ValueType>
struct container {
explicit container(std::size_t n) {
vec.reserve(n);
}
container& operator=(ValueType a) {
vec.push_back(a);
return (*this);
}
std::vector<ValueType> vec;
};
At this point we can define operator,
as:
template<typename ValueType>
container<ValueType>& operator,(container<ValueType>& m, ValueType a) {
m.vec.push_back(a);
return m;
}
which just pushes back a new element value.
And now you can easily see that the following works just fine and prints 1 2 3 4 5
:
int main() {
container<int> M(5);
M = 1, 2, 3, 4, 5;
for (auto i : M.vec) std::cout << i << ' ';
}
Live demo
I discourage this technique as much as possible. It forces you to have weird semantic for other operators, such as operator=
and really seem to add nothing to a simple use of std::initializer_list<T>
.
A saner example would be to have operator=
as follows:
container& operator=(std::initializer_list<ValueType> a) {
std::copy(begin(a), end(a), back_inserter(vec));
return (*this);
}
and then simply use brackets:
int main() {
container<int> M(5);
M = { 1, 2, 3, 4, 5 };
for (auto i : M.vec) std::cout << i << ' ';
}
Live demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With