Function overload using 'Const' - c++

There are 2 identical functions. One takes the argument with const keyword and another - without.
void A(const int* p);
void A(int* p);
int main()
{
int x;
A(&x);
return 0;
}
void A(const int* p)
{
cout << "2" << endl;
}
void A(int* p)
{
cout << "1" << endl;
}
Is it function overloading?
Why function without const will be called it my case?

Is it function overloading?
Yes. The two functions have the same name but different parameters, so they are overloads.
Why function without const will be called it my case?
Because x is not const. Try with a pointer to a const int, and you'll get the other overload:
const int y;
A(&y);

I think this is variation of the initial question :
from Stroustrup's tour of c++
template<typename T>
class C {
...
public:
...
T& operator[](int i);
const T& operator[](int i) const;
}
So as I understand it, the second method will target cases where the this-object is not intended to be modified.
I just wonder if the compiler is able to accurately guess that in every relevent case..

Related

const qualifier in a function

What is the difference between this three functions regarding using "const" qualifier
int& func (const int& var)
I know that the const qualifier keep input read-only and can not be changed inside the function.
int const func (int& var)
and this one also return const variable, but what does it mean? it means it can not be changed through the code?
int& func (int& var) const
and what about this one? I have no idea what this means.
int& func (const int& var)
^^^^^^^^^^^^^^
The highlighted part is an argument declaration. The part const int& is the type of the argument variable and var is the name of the variable.
Normally, constness applies to the left, but in this case, it is the left most token of the type. In this exceptional case, it applies to the right instead. To the right is int. Therefore it is a const int. As a whole, the type of the argument is reference to const int.
int const func (int& var)
^^^^^^^^^
The highlighted part is the return type declaration of the function. The return type is a const int object. Although it is well-formed, it never really makes sense to return a const int since the constness is irrelevant to the caller. Most compilers have options to warn in case of such declaration.
Technically, returning a const class object may be different from returning a non-const one, but I have not seen a case where that would be useful.
int& func (int& var) const
Const after the argument list applies to the function itself. A const member function may not be called on a non-const object or reference. The implicit *this argument of the member function will be const. Const qualifier cannot be applied on a non-member function or a static member function.
Regarding old version of the question...
What is the difference between this three functions regarding using "const" modifier
int& func (int& const var)
int& const func (int& var)
These two are ill-formed. Const qualifier cannot apply to a reference (although, you can have a reference to a const type, and such references are colloquially called const references).
You need to read the const quantifiers from right to left to understand them.
so for example int const func(int& var) returns a const int
Here is an example of the use:
#include <stdexcept>
#include <iostream>
int& func(const int& var)
{
std::cout << "func(const int& var) called\n";
throw std::runtime_error("not implemented");
}
int const func(int& var)
{
std::cout << "func(int& var) called\n";
throw std::runtime_error("not implemented");
}
struct A {
int& func(int& var) const
{
// i = 2; illigal since const function
std::cout << "func(int& var) const called\n";
throw std::runtime_error("not implemented");
}
int i;
};
int main()
{
try
{
const int i = 1;
func(i);
}
catch (std::exception) {}
try
{
int j = 2;
func(j);
}
catch (std::exception) {}
try
{
A a;
int k = 2;
a.func(k);
}
catch (std::exception) {}
}

C++ identical method signature but different return type

I have seen the following code:
template <class T>
class Type {
public:
Type() {}
T& operator=(const T& rhs) {value() = rhs; return value();}
T& value() {return m_value;}
T value() const {return m_value;}
private:
T m_value;
};
Why does the compiler not complain about
T& value() {return m_value;}
T value() const {return m_value;}
and how to know which one is invoked?
The two functions are actually not the same. Only the second function is declared as a const member function. If the object that the member is called from is const, the latter option is used. If the object is non-const, the first option is used.
Example:
void any_func(const Type *t)
{
something = t->value(); //second `const` version used
}
void any_func2(Type *t)
{
something = t->value(); //first non-`const` version used
}
If both functions were declared non-const or both were declared const, the compiler would (should, anyway) complain.
Why does the compiler not complain about
Because the const counts for a different function signature. Your assumption the function signatures are identical is wrong.
The function marked as const will be invoked for any const instance or reference of Type<T>.
and how to know which one is invoked?
Put a cout statement in the functions and test the following cases:
template <class T>
class Type {
public:
Type() {}
T& operator=(const T& rhs) {value() = rhs; return value();}
T& value() {
std::cout << "non const version" << std endl;
return m_value;
}
T value() const {
std::cout << "const version" << std endl;
return m_value;
}
private:
T m_value;
};
int main() {
Type<int> t;
t.value();
Type<int> rt = t;
rt.value();
Type<int>* pt = &t;
pt->value();
const Type<int> ct;
ct.value();
const Type<int>& crt = t;
crt.value();
const Type<int>* pct = &t;
pct->value();
}
Your assignment operator will call the non const version.
The const version should better look like
const T& value() const {
std::cout << "const version" << std endl;
return m_value;
}
because you can't always rely on RVO (return value optimization), and extra copies might be taken (especially for older compiler implementations).
Also note the assignment operator should return a reference to the current instance:
Type& operator=(const T& rhs) {value() = rhs; return *this;}
A couple of words on functions resolution priority. Compiler distinguishes between const/non const functions on following way:
If a class has only const function with given name and argument list, it will be called for constant and non-constant objects alike. After calling this function, object will 'assume' constness (even if it was not const), meaning that the function can only call other const functions.
If a class has only non-const function, it will be called for non-const objects. Attempt to call this function for const objects will lead to compilation error.
If a class has both functions available, const version will be used for const objects, non-const version will be used for non-const objects.
Thanks to #owacoder for pointing my attention to initial mixup in the description.

Template and operator overloading

I was going through code... I found a template class which is declared as shown below.
template <class T>
class tType
{
public:
T value;
T operator=(T val){ value = val; return value; }
tType<T> operator=(tType<T> &val){ value = val.value; return *this; }
operator T(){ return value; }
};
I also found operator overloaded like below...
******1******
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
I didn't understand when the above operator gets called... cos when I did...
int main(void)
{
tType<int> x;
x = 5;
if (5 == x)
{
cout << "Both are equal" << endl;
}
return 0;
}
The above said operator was not getting called... and was still working... I also wrote below code for testing and the below code snippet is getting called...
template<class T>
bool operator==(int x, tType<T>& val) { return (x == val.value); }
I wasn't to know who to call *****1*****
It's right that the reason your operator== isn't called is because of the missing const identifier. In this case, the literal 5 is unable to be passed as a variable reference for the paramater T& val. But, that's not quite the whole story.
As you point out, the code still compiles and runs even though the function isn't being called.
The reason your code still works is because of the conversion operator: operator T(){ return value; }.
A conversion operator allows implicit casts from one type to another. For example:
struct Number {
Number(int x) : value(x) { }
operator int() { return value; }
private:
int value;
};
int main() {
Number n(5);
int x = n; // 5 -- operator int() at work
int y = n + x; // 10 -- operator int() at work
Number z = x + y; // 15 -- Number(int) at work
cout << x <<" "<< y <<" "<< z << endl;
return 0;
}
Here, operator int() allows n to convert into an int for assignment to x and to convert to an int for addition with x (the resultant int is then assigned to y), while the unary constructor Number(int) allows the result of x + y to convert back to a Number.
In your code, 5 == x still compiles because the tType<int> x is converted into an int via its operator int() member function, and then that resultant int is compared against the literal 5.
However, this probably isn't a very good design for a class. For example, in order to compare two tType<T>s, a cast into T will be required for one of them.
template <class T>
bool operator==(const T& val, const tType<T>& tval) {
cout << "operator==(const T& val, const tType<T>& tval) was called." << endl;
return(val == tval.value);
}
//...
cout << ( tType<int>() == tType<int>() ) << endl; // calls operator==(const T&, const tType<T>&)
You would rather have an operator== for two tType<T>s.
Another even bigger problem is that this is not symmetric:
cout << (x1 == 5) << endl; // calls operator==(int,int) (the built-in function)
Yikes!
To address all of these, there is a very straightforward design solution. This is taken from Scott Meyers' book Effective C++ Third Edition (a phenomenal book).
Instead of converting back to a T with a conversion operator, the class should include an implicit unary constructor to convert T's up to tType<T>s, and should declare exactly one operator== for tType<T>s:
template <class T>
class tType
{
public:
tType<T>(const T &val) : value(val) { } // unary non-explicit constructor
tType<T> operator=(const tType<T> &val){ value = val.value; return *this; } // only need one
T val() { return value; }
private:
T value; // Note also value is private (encapsulation)
};
template<class T>
bool operator==(const tType<T>& a, const tType<T>& b) { return ( a.val() == b.val() ); }
The important changes:
Added a constructor that takes a single value; this allows converting Ts into tTypes.
Removed the assignment operator taking Ts (because now we can convert them to tTypes.
Only have one equality operator and it takes two const tType<T>&s, meaning operator== can handle any combination of Ts and tType<T>s (or, even better, anything convertible into either of those).
The == operator attempts to bind non-const references to the arguments - values like "5" are not amenable to that... the parameters should be const:
template <class T>
bool operator==(const T& val, const tType<T>& tval) { return val == tval.value; }
As that will still only support e.g. 5 == my_tType and not my_tType == 5, you may want to also provide...
template <class T>
bool operator==(const tType<T>& tval, const T& val) { return val == tval.value; }
...and for my_tType1 == my_tType2...
template <class T>
bool operator==(const tType<T>& tval1, const tType<T>& tval2) {
return tval1.value == tval2.value; }
This gives you maximum control of the comparisons. An alternative is to allow implicit construction of a tType from a T argument, but implicit construction and conversion operators are generally discouraged these days - they can lead to ambiguities and accidental creation of temporaries that can be hard to debug. A topic for another question....
When you say "The above said operator was not getting called... and was still working" - what was actually happening was that tType::operator T() (which returns value;) was being implicitly called, returning an int that could be compared - as an int - to 5. Hence - you had a comparison, but not using the custom operator==. This is a normal result of finding the "best match" for a function call.
Change the function
template <class T>
bool operator==(T& val, tType<T>& tval) { return(val == tval.value); }
to
template <class T>
bool operator==(T const& val, tType<T> const& tval) { return(val == tval.value); }
or
template <class T>
bool operator==(T val, tType<T> tval) { return(val == tval.value); }
Your function was not getting called since 5 cannot be converted to int&.

C++: Non-const operator taking preference over const overload

I have a class that represents a diagonal matrix. I only store the elements along the diagonal, so I don't waste space with a bunch of 0's. However, I still want to be able to use double brackets to access elements in the array. To get around that, I use an inner class, like this:
template <class T>
class DiagonalMatrix
{
private:
const T ZERO = 0;
int _size;
Vector<T> _data;
class row
{
private:
DiagonalMatrix<T>* _parent;
int _row;
public:
row(DiagonalMatrix<T>* parent, const int row)
: _parent(parent), _row(row) {}
T& operator[](const int i);
};
class const_row
{
private:
const DiagonalMatrix<T>* const _parent;
int _row;
public:
const_row(const DiagonalMatrix<T>* const parent, const int row)
: _parent(parent), _row(row) {}
const T& operator[](const int i) const;
};
friend class row;
friend class const_row;
public:
row operator[] (const int i);
const const_row operator[] (const int i) const;
// other stuff
};
And here are the relevant definitions:
template<class T>
typename DiagonalMatrix<T>::row DiagonalMatrix<T>::operator[](const int i)
{
if (i < 0 || i >= _size)
{
throw IndexOutOfBoundsException(i);
}
return DiagonalMatrix<T>::row(this, i);
}
template <class T>
T& DiagonalMatrix<T>::row::operator[](const int i)
{
if (i < 0 || i >= _parent->_size)
{
throw IndexOutOfBoundsException(i);
}
if (row == col)
{
return _parent->_data[row];
}
// TODO Add a real exception
throw "Cannot modify non-diagonal elements";
}
With similar definitions for the const versions, except the const operator[] returns a reference to the constant ZERO instead of throwing for non-diagonal elements.
So here is my problem: The non-const version is being called even when I don't need to modify anything. For example, this throws my error string:
DiagonalMatrix<double> diag(5);
// fill in the diagonal elements with some values
cout << diag[0][2] << endl;
However, if I remove the non-const versions of the operator, it behaves as expected and outputs a 0.
I've also tried something like:
T& at(const int row, const int col);
const T& at(const int row, const int col) const;
// in main:
cout << diag.at(0, 2) << endl;
But this has the same issue. So I have two questions:
1) Why does C++ choose the non-const version of the function over the const version even when I am not assigning to the result? Doesn't operator<< typically pass the right-hand object by const&?
2) How can I get around this? I'd rather not have separate get() and set() functions if I can help it.
1) Why does C++ choose the non-const version of the function over the const version even when I am not assigning to the result? Doesn't operator<< typically pass the right-hand object by const&?
It choose the non-const version because diag is not a const object.
2) How can I get around this? I'd rather not have separate get() and set() functions if I can help it.
You can define a const refrence to diag and use it to print values:
const DiagonalMatrix<double> &const_diag = diag;
cout << diag[0][2] << endl; // call const version
Or you define a function to print values and pass a const reference in:
void show_diag(const DiagonalMatrix<double> &diag)
{
cout << diag[0][2] << endl; // call const version
}
show_diag(diag);

Overloading operator []

Let's say I have a container class called MyContainerClass that holds integers.
The [] operator, as you know, can be overloaded so the user can more intuitively access values as if the container were a regular array. For example:
MyContainerClass MyInstance;
// ...
int ValueAtIndex = MyInstance[3]; // Gets the value at the index of 3.
The obvious return type for operator[] would be int, but then the user wouldn't be able to do something like this:
MyContainerClass MyInstance;
MyInstance[3] = 5;
So, what should the return type for operator[] be?
The obvious return type is int& :)
For increased elaboration:
int &operator[](ptrdiff_t i) { return myarray[i]; }
int const& operator[](ptrdiff_t i) const { return myarray[i]; }
// ^ could be "int" too. Doesn't matter for a simple type as "int".
This should be a reference:
int &
class MyContainerClass {
public:
int& operator[](unsigned int index);
int operator[](unsigned int index) const;
// ...
};
Returning a reference lets the user use the result as an lvalue, as in your example MyInstance[3] = 5;. Adding a const overload makes sure they can't do that if MyInstance is a const variable or reference.
But sometimes you want things to look like that but don't really have an int you can take a reference to. Or maybe you want to allow multiple types on the right-hand side of MyInstance[3] = expr;. In this case, you can use a dummy object which overloads assignment:
class MyContainerClass {
private:
class Index {
public:
Index& operator=(int val);
Index& operator=(const string& val);
private:
Index(MyContainerClass& cont, unsigned int ind);
MyContainerClass& m_cont;
unsigned int m_ind;
friend class MyContainerClass;
};
public:
Index operator[](unsigned int ind) { return Index(*this, ind); }
int operator[](unsigned int ind) const;
// ...
};
int&
returning a reference allows you too use the returned value as a left-hand side of the assignment.
same reason why operator<<() returns an ostream&, which allows you to write cout << a << b;