duplicating the same method with const? - c++

In C++, I see this code.
public:
Ports& GetPorts();
const Ports& GetPorts() const;
Why is it necessary to have another method with const?
How can a compiler decide which method is called?

If you call x.GetPorts() and x is a non-const object, the first version will be called. If x is a const object, on the other hand, the second version will be called. That kind of code is saying "if the object is modifiable, allow the result of GetPorts() to be modified; if the object is const, don't allow the result to be modified." The compiler will prefer the first version if it matches; however, it will not be present if the object is const and so the second version will be used instead.

Because the first overload is not a const method you can't call it over temporaries and const objects. If you provide a const overload you essentially support const objects.
The compiler will use the const overload for const objects and the none-const overload for none-const objects.
It is usually not necessary to provide an overload if your function is const, because const functions are as safe as they get: they work for both const objects and none-const objects.

This is necessary only if you want to have different behavior for const and non-const objects. Otherwise the second version is enough. A design decision.

Related

Using possibility to move constant reference

void foo (const std::string& str)
{
std::string local = std::move(str);
}
I'm really confused that this is allowed. Am I missing something and in some cases it can be used? Like if I know that it's safe to move this string, should I still use this construction, or is it something that is allowed by the compiler but in real life it should be never used?
It is allowed in a sense that this code is syntactically correct. std::move is nothing but a glorified cast, which takes type of the argument into account when casting. If your argument type is const &, the object is casted to the same const &&, and when you call
std::string local = std::move(str);
you end up calling copy constructor of the std::string, since it is the only suitable overload (std::string::string(string&& ) is not a viable candidate).
In the end, your move does exactly nothing, and can be seen as syntactic noise added to the code.
Am I missing something and in some cases it can be used?
It can be used in all cases where you can use:
std::string local = str;
This is effectively the same.
should I still use this construction
No. Doing this would be pointless and confusing.
In a more complex example, where the type is templated and may be const or non-const, this makes sense. That way you can copy from const and move from non-const
Like if I know that it's safe to move this string
You aren't moving the string. You cannot move from const xvalues.
If you know that it's safe to move a string, then pass an rvalue reference to non-const.

Same object as const and non-const, what should I assume to behave correctly?

I have a function of the form
return_type function(const argument_type & a, argument_type & b);
If the same object is passed as a and b, can I proceed with the function (thereby potentially modifying it) or halt?
I don't have the knowledge about how the compiler assumptions propagate on that case.
My guess is that non-constness assumptions for it being passed as non-const b should suffice and allow the modifications, but it's a guess.
Most answers were about being able to modify a or b, or call non-const methods. I know that if I pass the same object as both const and non-const I can do that. My doubt lies more in state that I'm going to left the program when the function returns, and if it can brake some compiler assumptions, for example:
class A(){
int value;
}
void function1(const A & arg1);
void function2(A & arg1);
void function3(const A & arg1, A & arg2);
A a;
a.value=5;
function1(a);
if(a.value==5){/*...*/;} // the if can be optimized out to true, because [a] was const
a.value=5;
function2(a);
if(a.value==5){/*...*/;} //must be checked, [a] could have been modified
a.value=5;
function3(a, a);
if(a.value==5){/*...*/;} // ???
Most similar question I've found (but not really it)
Modifying self within const method via non const pointer to self
The problem with
return_type function(const argument_type & a, argument_type & b);
and a call function( o , o ) is that the function probably
modifies the object through formal argument b, while
at the same time expecting formal argument a to remain unchanged.
So you will probably break the assumptions of the function, resulting in e.g. incorrect results or a crash.
There is one function that by design often has this kind of signature, namely the copy assignment operator. Its constant formal argument a is the explicity provided argument, and its mutable formal argument (if one can call it that) is the implicit *this. It can either check for self-reference (aliasing of the arguments) or it can copy and swap.
In summary, whether you can safely call the function with the same object as argument a and as argument b depends on the function, but chances are that you will violate the function's assumptions, that it has as an implicit precondition that the formal arguments refer to different objects.
You decide if that function may be called with the same argument given twice.
Anyway, you should not try to determine if you get the same object twice, as long as the correctness of your algorithm does not depend on it or you gave no guarantees.
They are passed exactly the same way at run time, same reference/pointer to exactly the same thing.
The difference with const happens only at compile time. The compiler will make sure you are calling only const methods and not trying to modify properties of this const object, otherwise it throws a compilation error, because you are not supposed to modify it.
My guess is that non-constness assumptions for it being passed as non-const b should suffice and allow the modifications, but it's a guess.
Yes, function can call non-const methods via b but not via a.
Intuitively, this means that function can change an object passed in via the const reference a if the same object is also passed in via the non-const reference b.
In general, const only makes guarantees about what you can or cannot do with a const variable. There may be other variables which refer to the const variable, or, to objects within it, that may enable the const variable to be modified by a function that doesn't look as though it's modifying a const variable.
Coming back to your case, it's upto functions and classes at a higher level than your function to themselves enforce constraints about what can and cannot be modified using const parameters, member functions, etc.

Why have two functions for operator overload?

I'm currently writing a double linked list using dynamic memory in C++ for one of my classes. I've already got the code written, I just had a question.
Our professor required us to write both an
int& operator[](int position)
AND an
int operator[](int position) const
function.
What was the point in doing two functions for the same operator? I'm sure there's some kind of logic behind it, haha. Is it just so I can do a = arr[i] and also do arr[i] = a?
If you have a const list object, you should only be able to read values from it. If you have a modifiable one, you should be able to both read and write values. The first is done with the const version, which will be called for a const object.
When your object is const, you can only use the const version of the operator, which by virtue of being const doesn't allow modification of your object or returning non-cons pointers/references to internal members. So when your object is non-const you need a non-const operator that allows modifications so you can write foo[i]=n
1) The const variant is for reading, e.g. when you assign a value to a variable. The compiler will give you an error when trying to modify the list value at the specified index. Example for const is a = arr[i] as you wrote.
2) The non-const variant is usually used when you actually set the value at the certain index of the list. Although you could use this variant for getting a value as well. However, then the compiler would not raise an error when your intention is to just read and your code would accidentally write. That could lead to subtle bugs which you can avoid by using const for such cases. Example for non-const is arr[i] = a as you wrote.
If you have both versions present, the non-const version version will be called for reading when you execute the indexing on a non-const object.
Is it just so I can do a = arr[i] and also do arr[i] = a?
Yes, that's what it's for.
if you have a const or a non-const list then you can perform the a = arr[i] assignment;
the version of the operator that returns an int& is so that you can perform arr[i] = a, which of course requires a non-const list.
Its just if you have a const variable of your object, lets call it A const a; then you are only allowed to call const functions, like your const overload of operator [] (...) const, which only provides reading. You are not allowed to call the non const operator [] (...) in this case.
Where you have a doubly-linked list object that is defined with the const qualifier (commonly called "a const object") or referred to via a pointer-to-const or a reference-to-const, you want to be enable reading but not writing. The const-qualified operator does that.
Where you have an object that is defined without the const qualifier, or referred to via a pointer-to-non-const or a reference-to-non-const, you want to enable both reading and writing. The non-const-qualified operator does that.
So, the reason you bother writing two overloads is to implement both behaviours.
If you only wanted reading, regardless of constness, then you would only write the const version because const-qualified member functions can be used to interact with both cases, whereas non-const-qualified member functions can only be used on the names of non-const-qualified objects (or via a pointer-to-non-const or a reference-to-non-const).
If you only wanted operator[] to apply to non-const objects then you would only write the non-const-qualified version. This might seem strange, since you don't expect operator[] to need the object to be modifiable, but as it happens this is exactly what std::map does with operator[].

C++ difference between adding const-ness with static_cast and const_cast of "this" object?

As per Scott Meyers, to prevent repetition of code in the const version of a getter and the non-const version of a getter, call the const version of the method from the non-const version: static_cast<const A&>(*this).Methodology(); however, in accidental usage due to an overzealous Visual Assist X Intellisense I typed: const_cast<const A&>(*this).Methodology(); and it worked just fine.
What are any and all differences in this case with using a particular cast?
IDE in use: Visual Studio 2010.
Assuming that the type of this is A*, there is no difference.
In general const_cast can cast aways the const specifier (from any level of indirection or template parameter)
static_cast<> can cast a type to another if the target type is in the source's type hierarchy.
They cannot do each other's work.
The reason they both worked in your case is because you have introduced const-ness, as opposed to having taken it away (calling from the non-const version of the function the type of this is A*, no const). You could just as well have written
const A& tmp = *this;
tmp.Methodology();
and it would have worked without the need for any casting. The casting is used for convenience and terseness to not have to introduce a new variable.
Note: you can use static_cast<> here as you know that you are casting to the right type. In other cases (when you cannot be sure) you need to use dynamic_cast<> that does a runtime type check to ensure the conversion is valid
After re-reading Item 3 from Effective C++ 3rd Ed. I realize that he was actually advocating using both. Add const to call the const version, then cast away the const-ness of the return value (if there is one). In my particular case, there is no const return value, just a const-function so the wrapped-by-const_cast<> version is not needed and in effect causes there to be no difference between the two calls in question
(p. 13) Item 3: Use const whenever possible
...
(p. 23) Avoiding Duplication in const and Non-
const Member Functions
...What you really want to do is implement operator[] functionality
once and use it twice. That is, you want to have one version of
operator[] call the other one. And that brings us to casting away constness.
...Casting away the const on the return value is safe, in this case,
because whoever called the non-const operator[] must have had a
non-const object in the first place....So having the non-const
operator[] call the const version is a safe way to avoid code
duplication, even though it requires a cast...
class TextBlock {
public:
...
const char& operator[](std::size_t position) const //same as before
{
...
...
...
return text[position];
}
char& operator[](std::size_t position) //now just calls const op[]
{
//cast away const on op[]'s return type;
//add const to *this's type;
//call const version of op[].
return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
}
...
};
As you can see, the code has two casts, not one. We want the
non-const operator[] ... To avoid infinite recursion, we have to
specify that we want to call the const operator[], but there's no
direct way to do that. Instead, we cast *this from its native type
of TextBlock& to const TextBlock&. Yes, we use cast to add
const! So we have two casts: one to add const to *this (so that our call to operator[] will call the const version), the second to
remove the const from the *const operator[]'s return value.

Should I return bool or const bool?

Which is better:
bool MyClass::someQuery() const;
const bool MyClass::someQuery() const;
I've been using 'const bool' since I'm sure I remember hearing it's "what the ints do" (for e.g. comparison operators) but I can't find evidence of that anywhere, mostly due to it being difficult to Google and Intellisense not helping out any ;) Can anyone confirm that?
To me returning const values (this isn't just about bools) makes more sense; it'll prevent temporaries being modified, which is almost always going to be a programmer mistake. I just want something to back that up so I can extol returning const values to my colleagues :)
This is the case when const adds no value but inflates the code and makes the reader think more. What's the point of this const? The caller can copy the value into some non-const variable and do whatever he wants with it anyway.
So you know it's right, you're just after the Voice of Authority?
Preventing accidental modification of temporaries is very valuable. In general, you should declare as many things as you possibly can const, it protects you from a variety of accidents and gives the optimiser useful hints.
D'you have a copy of Scott Meyers' "Effective C++" around? Point them at Item 3 (page 18 in the third edition) ;)
It gives the example of
class Rational {...};
const Rational operator* (const Rational& lhs, const Rational& rhs );
if( (a * b) = c ) // declaring operator *'s return value const causes error to be caught by compiler
Note that if((a*b) = c) won't compile for built-in types anyway, so it is very relevant here whether we're talking built-in types (your question asks for bool) or user-defined types.
For built-in types it makes no sense at all, so it shouldn't be used. And for user-defined types, I'm in jalf's camp: What if the caller wants to modify the returned object?
I'm not convinced that if((a*b) = c) is such a good argument for returning const user-defined types, since I can't remember the last time I've seen a compiler not warn about this.
To be a little more specific, only "objects" can be const. The C++ standard's definition of "object" includes everything an lvalue refers to ("has a name") and class-type temporaries. A boolean return value is an rvalue of a non-class type which is why a standards-compliant compiler will just ignore "const" in this case. As others said already, it's useless in this context.
When you returning a refernce to a member variable it makes sense to make it const. Here you are returning a copy, hence there is no need of const.
The const modifier is only used for return types that are returned by reference (either as reference const SomeObject& or via a pointer const SomeObject*), so the caller won't be able to modify the object via the reference/pointer. Primitive types are returned by value, which means that the caller receives a copy of the the object, not the object itself.
Therefore, const is not really appropriate for returned value types. Since the copy is outside of the control of the called function, the called function should not dictate to the caller that it cannot be changed.
This is an ancient post, but I think it's worth mentioning there is a potential corner case here since C++11. While, as stated by others, it will make no difference whether you use const bool or bool as return type in most cases, if you are using C++11 decltype and associates, e.g. result_of, you could declare a variable with the same type as the returning value of some function, and so the const would actually have an effect in this case.
It completely doesn't matter. Therefore, the consensus is to return just bool.
The reason that it doesn't matter is that you can't call non-const member functions anyway; bool is not a class or struct.
As bool is going to be copied, it's the same, to put const or not. Plus you'll may have some compil problems.
const return type
SUMMARY:
The value of a return type that is
declared const cannot be changed. This
is especially usefull when giving a
reference to a class’s internals, but
can also prevent rarer errors.
const bool func();
bool f = func();
0 errors, 0 warnings. What have you accomplished other than unnecessary code inflation?