implementing multiple subscription operators for template matrix (operator()) - c++

I've received an excercise to implement a generic Matrix class.
One of the tasks is as follows: "Overload operator() which gets parameterse (unsigned int, unsigned int) twice, once as const and once as a non-const.".
Now, after much searching, I understood that this should be how their signatures:
T operator()(unsigned int rows, unsigned int colls) const; //cout << "A" << endl;
T & operator()(unsigned int rows, unsigned int colls); //cout << "B" << endl;
however, no matter which way I'm trying to call them only the second one is called:
int main()
{
Matrix<int> mat(2, 3);
mat(1, 1) = 3;
int i= (9 + mat(1, 1)) ;
i = mat(2, 1);
cout << i << endl;
if (i == mat(1, 2)) {}
int j = Matrix<int>(2, 2)(1, 1); //calls constructor and then subscription.
}
The output will be:
B
B
B
0
B
B

Good on the instructor for requesting operator(). There is hope for the universe.
This isn't so much of an rvalue/lvalue thing as it is constant/non constant.
The const on the end of the method definition states (and the compiler will do a and does a reasonable level checking that it won't) that calls to the method will not change the object's state. Absolutely necessary if you want to be able to call methods on a constant object.
If you add the following function to your test code:
void consttest(Matrix<int> &mat, const Matrix<int> &cmat)
{
mat(1,1) =4;
cmat(1,1) =4;
}
And call it like this:
consttest(mat, mat);
You'll see that good ol' rvalue/lvalue stuff in action. Sadly, you won't get to see your see your const operator() getting called because it won't compile. Pretty good test in it's own way, the method is guarded pretty well from mistakes, but a more useful test for functionality is:
void consttest(Matrix<int> &mat, const Matrix<int> &cmat)
{
std::cout << mat(1,2) << std::endl;
std::cout << cmat(1,2) << std::endl;
}
By the way, here's a nice chat on lvalues and rvalues: What are rvalues, lvalues, xvalues, glvalues, and prvalues?

Related

Is there an efficient way to make reference to constants actually const instead of read only?

Let's look at the following C++ code:
#include <iostream>
int main()
{
int z = 2;
class A {
public:
const int & x;
A(const int & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
z = 3;
a.show();
}
The program prints: 2 and 3
It clearly shows that while inside class A x can't be modified, it merely means it's read only, because I can change it's value from outside.
Of course I can make it a copy stored inside class A, but I'm wondering if there is (or if there is a proposal?) of a way to say to class A that the member x will be truly constant instead of merely read only, with the meaning of a promise that the external code won't change it ?
To my eyes it looks like something related to the meaning of the C restrict keyword, but I've not heard of any such C++ feature yet. Do you ?
Constness is an attribute of the actual variable.
The term const int& x simply means "x is a reference to an int which it will not modify" and of course the compiler enforces this.
If you want the actual variable to which x refers to be const, simply declare it so:
#include <iostream>
int main()
{
const int z = 2; // declared const. Nothing may ever modify it
class A {
public:
const int & x;
A(const int & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
z = 3; // this is a logic error, caught by the compiler.
a.show();
}
compiling correctly produces the error:
./const.cpp:41:7: error: read-only variable is not assignable
z = 3;
~ ^
1 error generated.
You're looking for D's immutable keyword, which was introduced as a new concept in that language precisely because, unfortunately, the answer is no: it does not exist in C++.
Constness in C++ does not mean immutability, but that the variable in question is read-only. It can still be modified by other parts of the program. I understand your question as to whether it's possible to enforce true immutability in a called function without knowing what the caller is doing.
Of course you can create a template wrapper class which accomplishes the task:
template <typename T>
class Immutable
{
public:
template <typename ...Args>
Immutable( Args&&...args )
: x( std::forward<Args>(args)... )
{}
operator const T &() const
{
return x;
}
private:
const T x;
};
As long as you do not reinterpret_cast or const_cast you will have truly immutable objects when you wrap them with Immutable<T>.
However, if you have a constant reference to some object, there is no way to tell, if some other part of the program has a non-constant access to the object. In fact, the underlying object might be a global or static variable, that you have read-only access to, but functions you call might still modify it.
This cannot happen with Immutable<T> object. However, using Immutable<T> might impose an extra copy operation on you. You need to judge yourself if you can live with that and if the cost justifies the gain.
Having a function require an const Immutable<Something> & instead of const Something & as an argument affects the calling code. A copy operation might be triggered. Alternatively, you can ask for an Immutable<Something> & without the const. Then no accidental copies will be triggered, but the calling code must pass a reference to Immutable<Something> object. And rightly so, because if the caller received a const & as an argument then the caller does not know, whether the object might get modified by someone else in the program. The caller has to create the object itself or require an immutable object to be passed to it as a reference.
Your original question
Here's your original problem with Immutable<int> & instead of const int &.
#include <iostream>
int main()
{
Immutable<int> z = 2;
class A {
public:
const Immutable<int> & x;
A(Immutable<int> & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
//z = 3; // this would fail
a.show();
}
An other example
Here's how it works: If you write
void printAndIncrementAndPrint( int & i1, const int & i2 )
{
std::cout << i2 << std::endl;
++i1;
std::cout << i2 << std::endl;
}
int main()
{
int i = 0;
printAndIncrementAndPrint( i, i );
}
then it will print
0
1
into the console. If you replace the second argument of printAndIncrementAndPrint() with const Immutable<int> & i2 and keep the rest the same, then a copy will be triggered and it will print
0
0
to the console. You cannot pass and Immutable<int> to the function and a int & to the same underlying data without breaking the typesystem using const_cast or reinterpret_cast.
I think this is a design problem for the programmers, not the language. A const variable means for any user of that variable, they should not change the value of that variable. Our compiler is smart enough to help us make sure of that. So A is a user of z and if you want A know that A::x references to a const variable, then you should make z a const int. The const reference is just to keep the contract between the user and the provider.

Passing Eigen::Map<ArrayXd> to a function expecting ArrayXd&

Some of my Eigen C++ methods need to be callable from plain C++, therefore I want to provide overloaded functions that accept c arrays and map them to ArrayXd using Eigen::Map.
The code I currently have looks like this:
bool Dmp::executeStep(double* position, double* velocity,
double* acceleration, const int len)
{
Map<ArrayXd> posMap(position, len);
Map<ArrayXd> velMap(velocity, len);
Map<ArrayXd> accMap(acceleration, len);
return executeStep(posMap, velMap, accMap);
}
bool Dmp::executeStep(ArrayXd& position, ArrayXd& velocity, ArrayXd& acceleration)
{
//Code that modifies position, velocity and acceleration
}
This does not work because there is no known conversation from Map<ArrayXd> to ArrayXd&.
What is the correct way of doing this?
edit:
The answer that luk32 pointed out below would work, however it involves moving my code to the header file which is something I would like to avoid if at all possible.
This is exactly the purpose of the Ref<> class:
bool Dmp::executeStep(Ref<ArrayXd> position, Ref<ArrayXd> velocity, Ref<ArrayXd> acceleration)
{
}
You should make the executeStep a template function. Or use their other facilities like Ref There is a whole comprehensive tutorial in docs on Writing Functions Taking Eigen Types as Parameters.
I am not sure if Map has a more direct parent than EigenBase (maybe Dense really not sure), but as it is most general it should work:
template <typename Derived>
void Dmp::executeStep(EigenBase<Derived>& pos,EigenBase<Derived>& vel, EigenBase<Derived>& acc )
{
// fun ...
}
Of course you need to declare it as a template member too.
I really highly suggest reading the whole tutorial.
Using Ref implementation. I am not sure however if there is a copy from Map to MyMatrix made. Ref do not accept Map objects as it seems to cast them to DenseMatrix.
#include <Eigen/Core>
#include <iostream>
using namespace Eigen;
typedef Matrix<int,2,4> MyMatrix ;
void print_size(const Ref<const MyMatrix>& b)
{
std::cout << "size (rows, cols): " << b.size() << " (" << b.rows()
<< ", " << b.cols() << ")" << "\n";
}
int main()
{
int array[8];
for(int i = 0; i < 8; ++i) array[i] = i;
Map<MyMatrix> map(array);
std::cout << "Column-major:\n" << map << "\n";
print_size(map);
}

Why do C++ function objects need reference type member variables?

This is a newbie C++ question. I was reading the "Function object" article in Wikipedia. The article has an example in C++ similar to the following:
struct printClass {
int &count;
printClass(int &n) : count(n) {}
void operator()(int &i) const {
count++;
cout << i << "[" << count << "] ";
}
};
int main(int argc, char** argv) {
vector<int> a(5, 7);
a[4] = -1;
a.resize(10, 3);
int state = 0;
for_each(a.rbegin(), a.rend(), printClass(state));
}
I have 2 questions:
Why does it fail to compile when count is a regular variable not a reference type? Demo
Why does it fail to compile it I change the ctor to the following? Demo
printClass(int &n) { count = n; }
Thanks.
EDIT: Thanks for explaining. I see that the following version works, too. Is there a reason for chosing one over another?
struct printClass {
int count;
printClass(int n) { count = n; }
void operator()(int &i) {
count++;
cout << i << "[" << count << "] ";
}
};
EDIT: Based on iammilind's reply, here is the 3rd version that works too using const_cast<int &>.
struct printClass {
int count ;
printClass(int n) : count(n) {}
void operator()(int &i) const {
const_cast<int &>(count)++;
cout << i << "[" << count << "] ";
}
};
(1) Why does it fail to compile when count is a regular variable not a
reference type?
This is a very interesting question. The question should be rather, why the code compiles when count is declared as a reference. :)
The regular variable fails because int count is not modifiable inside a const qualified function operator()(int &i) const;.
References are little different. In your code you are declaring the method as const, which means that count which is referring to i, now cannot refer to anything else.
But that's anyway not possible due to nature of references :). One cannot change reference binding after the initialization.
operator() just checks whether you are changing the binding of count to anything else or not? And the answer is always no. Because count++ changes the value referred by count and not the binding.
In your code, it doesn't matter if a member method is const or not when it comes to int& count.
Relate int& count; to int* const p_count; and try to simulate the situation on your own.
(2) Why does it fail to compile it I change the ctor to the following?
CountFrom(int &n) { count = n; }
Because reference must be assigned to a variable while initialization. In simple example;
int i, &r; // error, because 'r' not initialized
r = i; // this is not initialization but a copy
On a side note, you should be extra careful when you are dealing with reference variables inside a class. Because it's easy to mess up with their scope and validity.
For example, here the validity of count is dependent on the scope of i.
Edit: After your 2nd edit, it's very trivial to know why that version works.
Because count is now a simple variable. It can be skipped from initialization in the initializer list of the constructor unlike reference.
Moreover the const correctness of the operator() is gone, so any member variable of the class can now be modified inside it.
You should choose a const version of the member method, if you want to state that no class member "must" change inside it (unless any variable is mutable or you use const_cast). In all other cases use the normal version of the member method. They both can co-exist as well depending on your business logic. This is a bit of a broad question and it's worth to have another thread for this.

const object initialization as `const Vect const_vect = Vect() << 1 << 2;`

Some hours ago I read this question in which the user initialized a const object as
const QList warnings = QList() << 0 << 3 << 7;
Indeed, this expression somehow hurt me because going against the concepts I have of const and of overloading operator<<.
I tried to define an operator<< possibly allowing for the mentioned expression and here is what I got:
typedef vector<int> Vect;
Vect operator<<(Vect v, const int i){ //ByVal v, This way it works, but at which cost?
v.push_back(i); //v is copied at every call!
return v;
};
//Here is where I build the object
const Vect const_vect = Vect() << 1 << 2;
//it works fine but I see massive overhead due to copies..#_#
//Just for testing
int main() {
for(auto e = const_vect.begin(); e!=const_vect.end() ; ++e){
cout << *e << " ";
}
return 0;
}
The previous code (which is also here) works fine.
The following, on the other hand, is the expression I would have expected from the definition of operator<<:
Vect& operator<<(Vect& v, const int i){ //ByRef v<-this I would have expected;
v.push_back(i); //however it can't work because receives and
return v; //returns reference to temporary object.
};
My question is: what am I missing? is the operator<< defined in QList differently implemented from mine, in particular, can it receive and return ByRef?
Secondly, is perhaps the aforementioned a standard procedure to initialize complex const objects?
Thirdly (maybe inconvenient), how would such an expression handled by the compiler? what is done at compile-time and what at run-time?

Copy part of a class

I want to copy a part of a class to a buffer. I need this to make something that can look if there are changes in a class, and send it over the network to update the changes on the server.
I made a template class that can back-up and restore classes. Now I am making the "look for differences" function. I want that the user can define how big the memory blocks will be. This split the class in parts and takes less data to send.
The problem is that I can't copy a part of the class memory to the heap, I can't get the address correct. If I do "address of the class" + "0x04". Then I don't get the correct addres.
This is an exaple that I made:
testclass test1;
testclass test2;
test1.set(1,1);
test2.set(1,2);
cout << &test1 << " " << (&test1 + 0x04) << endl; //0018FF24 0018FF44
memcpy(&test2,&test1 + 0x04,4);
test2.echo(); //Wrong data!
The header:
class testclass
{
int test,test2;
public:
void set(int a, int b) {test = a, test2 = b;}
void echo() {cout << test << " " << test2 << endl;}
};
I hope someone help me with this problem.
Thanks!
Basically, you can't muck around with pointers like that. You generally can't rely on the compiler to coincidentally put meaningful data there.
If you want the address of members you should write &(test1.test2) not &test1+0x04 because even IF an int is 4 bytes and IF the compiler hasn't padded the structure and IF you or someone else hasn't changed the contents of the class, then &test1+0x04 really means "&test1 plus 4*sizeof(test) bytes", it's another way of reaching (&test1)[4] in terms of pointer-array-equivalence.
Also, you can't memcpy over classes in general and expect meaningful results, unless they are POD.
If you want to compare instances of a class, you should write a function which compares each of the members in turn.
You can't write a general-purpose method for this because C++ is not a reflective language. That means you can't write code which magically knows the names and types of the members of a class.
So, if you want to compare and patch data like this, you will need to do something like this:
struct Foo {
int a;
int b;
void export_differences (std :: ostream & o, const Foo & f) {
if (a != f.a) o << "a " << f.a << " ";
if (b != f.b) o << "b " << f.b << " ";
o << ";";
}
void import_differences (std :: istream & i) {
std :: string s;
while (i >> s) {
if (s == "a") i >> a;
else if (s == "b") i >> b;
else if (s == ";") break;
else throw std :: runtime_error ("bad input");
}
}
};
You will have to write something like this for each class you want to patch.
Where does the magic 0x04 and 4 come from?
If this works, it is just because of a particular alignment and implementation.
Better a more structured way:
class testclass
{
int test,test2;
public:
void set(int a, int b) {test = a, test2 = b;}
void echo() {cout << test << " " << test2 << endl;}
void backup_to(testclass& s)
{ s.test2 = test2; }
bool has_changed_respect(const testclass& s)
{ return s.test2 == test2; }
friend std::ostream& operator<<(std::ostream& s, const testclass& a)
{ return s << "testclass["<<&a<<"]: test="<<a.test<<", test2="<<a.test2<< std::endl; }
};
int main()
{
testclass t1, t2;
t1.set(1,1);
t2.set(3,4);
std::cout << t1 << t2;
t1.backup_to(t2);
std::cout << t2;
t1.set(5,6);
cout << t1 << t2 << t1.is_changed_respect(t2) << std::endl;
return 0;
}
&test1 + 0x04 means to add 4 times the sizeof testclass to the address of test1, and the resulting pointer has type testclass*. It would point to the fifth element of an array whose first element is at the address of test1, except that test1 isn't part of an array, so the addition has undefined behavior.
What you seem to want is to add 4 bytes to the address of test1. You can do that for example with ((char*)&test1) + 4, which results in a pointer of type char*. Beware that the standard doesn't guarantee that sizeof(int) is 4, nor does it guarantee that offsetof(testclass, test2) == sizeof(int).
You're permitted to inspect any object's memory as char* or unsigned char*. But there are some limits on how useful this ability is:
Classes can have padding bytes in them, that can take any values. So just because two objects have different byte values in memory doesn't mean they aren't equal.
Non-POD classes can have pretty much arbitrary "extra stuff" in them, put there by the implementation, and cannot safely be copied byte-wise.
Classes with pointer members often cannot safely be copied byte-wise, and certainly not to another machine over the network.
Even if the class is POD, if you send it over the network then you have to make sure that the class has the same layout on the two machines. This is not necessarily the case if the code was compiled with different options, by different compilers, or for different architectures, but sometimes it is the case.
1) At first, you need your class to be POD. At least you can take out data members to separate structure.
2) Then, if choose your offset granularity = 1, 2, 4 or 2^n bytes as necessary; and determine the type that suits this requirement: 2^n == sizeof(chunk_type). For example, you wish to byte-to-byte comparison, so cast you pointer to _State (or MyClass see #1) to desired type: (char*)this->m_state.
Here is the function, that tries to find the first chunk that differs in both classes, and returns its offset or -1 if no differences found.
class MyClass {
struct _State {
int a,b
};
_State m_state;
public:
typedef char chunk_type;
int next_diff_pos(const MyClass& other, size_t offset = 0) const {
chunk_type *pThis = &m_state,
*pOther = &other.m_state;
if (offset < sizeof(_State)) {
size_t n = offset;
while(*pThis++ == *pOther++ && n < sizeof(_State))
n++;
// We need to test this again, because of ambigous while condition
if (n < sizeof(_State))
return n;
}
return -1;
}
};
PS: Of course, your chunk_type must have == operator defined (this done already for char, int and other scalars).
(I've not tested the code)