Error: passing 'const xxx' as 'this' argument discards qualifiers - class

I am trying to implement bigint class in c++, it's not completed yet, i have encountered some errors that i am unable understand.
I have erased all other functions (as they are unnecessary in this case)
and karatsuba is not yet completed (but that should't pose a problem in this case).
In the multiply function (overloaded * ) my compiler gives an error:
passing 'const BigInt' as 'this' argument discards qualifiers [-fpermissive]
at line
ans.a = karatsuba(n,m);
I understand that this would occur when i am trying to change a constant object or object passed to a constant function, in my case i am merely creating a new vector and passing it to karatsuba function.
Removing const from overloded * gets rid of this error.
So,does this mean that a constant function can't change anything at all? (including local variables?)
class BigInt {
typedef long long int ll;
typedef vector<int> vi;
#define p10 1000000000;
#define range 9
vi a;
bool sign;
public:
BigInt operator * (const BigInt &num) const
{
vi n(a.begin(),a.end()),m(num.a.begin(),num.a.end());
BigInt ans;
ans.sign = !(sign ^ num.sign);
while(n.size()<m.size()) n.push_back(0);
while(n.size()>m.size()) m.push_back(0);
ans.a = karatsuba(n,m);
return ans;
}
vi karatsuba(vi a,vi b)
{
int n = a.size();
if(n <= 16)
{
// some code
}
// some code
return a;
}
};

Ok so after googling a bit more, i realized that this pointer is implicitly passed to the oveloaded * and then on to karatsuba (as it is a member function of the class), and as karatsuba is not a constant function, there is no guarantee that it won't change the object contents, hence this error is triggered.
One solution is to declare karatsuba as static, as static member functions don't receive this pointer (they can even be called with out a class object simply using :: operator) , read more about them from here Static data members and member functions.
All that is needed to be changed is :-
static vi karatsuba(vi a,vi b)
{
int n = a.size();
if(n <= 16)
{
// some code
}
// some code
return a;
}

Related

Understanding constructors and final [duplicate]

class X extends Y {
X(int a, int b) : super(a,b);
}
Can someone give me an explanation about the syntax meaning of the colon :?
This feature in Dart is called "initializer list".
It allows you to initialize fields of your class, make assertions and call the super constructor.
This means that it is not the same as the constructor body. As I said, you can only initialize variables and only access static members. You cannot call any (non-static) methods.
The benefit is that you can also initialize final variables, which you cannot do in the constructor body. You also have access to all parameters that are passed to the constructor, which you do not have when initializing the parameters directly in the parentheses.
Additionally, you can use class fields on the left-hand of an assignment with the same name as a parameter on the right-hand side that refers to a parameter. Dart will automatically use the class field on the left-hand side.
Here is an example:
class X {
final int number;
X(number) : number = number ?? 0;
}
The code above assigns the parameter named number to the final field this.number if it is non-null and otherwise it assigns 0. This means that the left-hand number of the assignment actually refers to this.number. Now, you can even make an assertion that will never fail (and is redundant because of that, but I want to explain how everything works together):
class X {
final int number;
X(number): number = number ?? 0, assert(number != null);
}
Learn more.
It's ok to access non static member in initializer list.
class Point {
num x, y;
Point(this.x, this.y);
Point.origin(): this.x = 10, this.y = 10;
}
main() {
Point p = Point.origin();
print(p.x); // 10
}

Systemverilog const ref arg position when constructing an object

I am creating a class that needs a reference to the test bench's configuration object. Since the configuration must be intact throughout the simulation, I pass it as a const ref object. Here is a sudo code that I want to run:
class tb_config;
int unsigned rate;
int unsigned chnls[];
const int unsigned nb_chnls;
function new (int unsigned rate, int unsigned nb_chnls);
this.rate = rate;
this.nb_chnls = nb_chnls;
chnls = new[nb_chnls];
endfunction
endclass
class tx_phy;
static int phy_id;
tb_config cfg;
function new (int unsigned phy_id, const ref tb_config cfg);
this.phy_id = phy_id;
this.cfg = cfg;
endfunction
endclass
module test;
tb_config cfg = new(100, 4);
tx_phy phy = new( 1234, cfg);
endmodule
The code above works perfectly fine and it meets my expectation. But if I change the arguments in tx_phy::new to function new (const ref tb_config cfg, int unsigned phy_id); and pass the values to the constructor accordingly I get the following error in Cadence Incisive:
invalid ref argument usage because actual argument is not a variable.
Also same thing happens when I test it with Aldec in edaplayground: https://www.edaplayground.com/x/5PWV
I assume this is a language limitation, but is there any other reason for that??
The reason for this is because the argument kind is implicit if not specified. You specified const ref for the first argument, but nothing for the second argument, so it is also implicitly const ref. Adding input to the second argument declaration fixes this.
function new (const ref tb_config cfg, input int unsigned phy_id);
I also want to add const ref tb_config cfg is equivalent to writing
function new (tb_config cfg, int unsigned phy_id);
Both of these arguments are implicitly input arguments, which means they are copied upon entry.
A class variable is already a reference. Passing a class variable by ref means that you can update the handle the class variable has from within the function. Making the argument a const ref means you will not be able to update the class variable, but you can still update members of the class the variable references. There is no mechanism to prevent updating members of class object if you have a handle to it other than by declaring them protected or local.
The only place it makes sense to pass function arguments by ref in SystemVerilog is as an optimization when the arguments are large data structures like an array, and you only need to access a few of the elements of the array. You can use task ref arguments when the arguments need to be updated during the lifetime of the task (i.e. passing a clock as an argument).

Shall I build a destructor in this classes?

I am currently working on building an ABM model using C++.
I have classes that have the need to interact with each other, because e.g. class B needs to examine values in class A and return some evaluation on it, which then class C might want to read. Classes need not to change other classes values, only to read from them.
Class B in my current implementation has a po
inter to a vector containing all members of Class A. The pointer is there for two order of reason: it makes easier to initialize the vector, and the vector is left in the scope of main so that I can access and loop over it, calling the members of class A for each agent.
My MCVE:
#include <iostream>
#include <vector>
using namespace std;
class A; // Forward declaration
class B{
int id,
some_value;
vector<A> * A_vec;
public:
// Overloaded constructor
B(int ID, vector<A> & PTR)
{
A_vec = & PTR;
id = ID;
some_value = 0;
};
// Copy Constructor
B( const B& that ):
id(that.id),
some_value(that.some_value)
{
// Pointer ??
};
// Non-default destructor -> uncomment leads to seg_fault
/*
~B(){ delete [] A_vec;};
*/
// Assignment operator
B& operator=(const B& that)
{
id = that.id;
some_value = that.some_value;
// Pointer ??
return *this;
};
//Methods to update different variables go here ..
void do_stuff();
};
class A{
B & class2_ref;
vector<double> o;
public:
int stuff;
// Overloaded constructor
A(int STUFF, B & REF, vector<double> O):
class2_ref(REF),
o(O)
{
stuff = STUFF;
};
// Methods to update different variables go here ..
};
void B::do_stuff()
{
int L = A_vec->size();
for(int l = 0; l<L; l++) some_value += (*A_vec)[l].stuff; // Perform some operation
};
int main(){
int I = 5; // Number of objects of A
vector<double> O(12,2); // Some numbers in here
B b(0,A_vec);
for(int i = 0; i< I; i++)
{
A a(i,b,O);
A_vec.push_back(a);
}
b.do_stuff();
cout<< "Debugging MCVE" << endl;
return 0;
}
My question then is:
Should I implement the destructor/copy constructor/assignment operator in class B? What about class A ? If so, can you please point me to the correct syntax(for the destructor the one above in comments leads to seg fault).
My understanding is that this might be one of the case in which I am happy with a "shallow" destruction of the pointer, because both class B and vector<A> will go out of scope at the return statement. class B owns the pointer, which gets destructed when it is due, and the same for vector.
But then, what about the other member from the rule of three?
There is only one object of class B planned, but I might (small chance) want to generalize later on.
if a class have a pointer type, you should implement a destructor, and i would suggest implementing a copy and an assignment operator as well, else you will be dealing with the same object from 2 different places, which could cause you some errors, for example -
void someFunction(B &b)
{
B a = b;
}
B b(0,A_vec);
someFunction(b); //After finishing someFunction, it will try to delete the vector from a , but it is the same vector you used in b.
b.do_stuff(); // Would cause a seg error
And for the destructor syntax, just delete the vector, not its content, it will use the vector default destrctor on the content:
delete A_vec
just make sure you dont use it if its not initialized, i would suggest just building a empty vector on each ctor of the class, that way you wont get a seg fault and you can use delete.

Difference between param[out] and return in doxygen?

What is the difference between \param[out] and \return in Doxygen? They both seem to document the output / return of a function. Is the difference due to void functions which don't have a return value and only param[out] would be valid?
Out parameters are different from return values. Take this example in C:
/**
* \param[in] val Value calculations are based off.
* \param[out] variable Function output is written to this variable.
*
* \return Nothing
*/
void modify_value(int val, int *variable)
{
val *= 5;
int working = val % 44;
*variable = working;
}
The function returns nothing, but the value to which variable points is changed, hence we call it an output parameter. It represents an 'output' of the function in that we expect it to be modified somehow by the function. val, on the other hand, is an 'input' parameter because it is not modified (and, indeed, cannot be modified from the perspective of the function's caller, since it is passed as a value).
Here's a slightly more useful and realistic example:
typedef struct data {
int i;
int j;
...
} data;
/**
* \param[in] val Initialising parameter for data.
* \param[out] dat Data pointer where the new object should be stored.
*
* \return True if the object was created, false if not
* (i.e., we're out of memory)
*/
bool create_data(int val, data **dat)
{
data *newdata;
newdata = (data*)malloc(sizeof(data));
if(newdata == NULL)
{
*dat = NULL;
return false;
}
newdata->i = val;
*dat = newdata;
return true;
}
In this case, we construct some complex object inside the function. We return a simple status flag that lets the user know the object creation was successful. But we pass out the newly-created object using an out parameter.
(Although, of course, this function could easily just return a pointer. Some functions are more complex!)
As a simpler answer, [out] parameters are only for results returned via parameters not the return value. It is quite reasonable to have a function which has a return value and also has optional return data, eg: one I'm just writing has the signature:
/**
Determine UTF type of a file.
Unless a UTF8 file has a BOM, it is regarded as unknown.
#param [in] path Path to file suitable for ifstream
#param [out] bomWasFound optional return flag to indicate a BOM was found, really only useful for UTF8
#return an enum indicating type, default utf_unknown
*/
UtfType CheckFileType(const std::string& path, bool* bomWasFound=0);

difference between static T const and static const T

Assuming that T is an arbitrary type and we're talking about Objective-C. Then what is the difference between
static T const x = ....
and
static const T x = ....
?
They are the same.
A little background about const:
Objective-C, just like C, uses the Clockwise/Spiral Rule. In a case where you have only modifiers at the left side of the variable (of foo) you read stuff going from right to left:
int * const * var;
is read: var is a pointer to a constant pointer to integer.
However const has the same effect when it's before or after the first type:
int const var; // constant integer
const int var; // constant integer, same as above
static, instead, affects the whole variable: it's the variable to be static, not the element pointed by it or anything else: a pointer to integer can be used both to point to a static integer, or to an automatic integer without distinction, and C doesn't provide a syntax to declare a pointer able to point to static variables (or to automatic variables) only.
static int * x; // x is a static pointer to integer
int static * y; // as above y is a static pointer to integer
int * static z; // THIS SYNTAX IS NOT ALLOWED
// but if it was, it would mean the same thing
For this reason I prefer to place it before any const modifier, but it doesn't actually matter.
static const int * const * x; // this is what I do
I believe the distinction is only important for pointer types; for example 'char *'.
const char *p means that the buffer pointed to by p cannot be updated but pointer p itself can be changed (typically incremented with p++), for example:
void f(const char *p)
{
while (*p != '\0')
{
putc(*p);
p++;
}
}
char * const p means that the buffer pointed to by p can be updated but pointer p cannot be changed.
EDIT Thanks for JeremyP for the following comment:
It's quite common in Apple's APIs to define string constants (instead of using #defines), especially if the string is an NSString i.e. NSString * const kFoo = #"bar";