Function overloading behavior with const
I am working on g ++ and here I tried to overload a function by simply adding a parameter const
to a parameter. It works fine and when it starts it calls the function withoutconst
- Is this behavior specified in the C ++ standard?
-
What is the reason it calls the function without
const
void print(const std::string& str){std::cout << "const" << str << std::endl;} void print(std::string& str){std::cout << str << std::endl;} int main() { std::string temp = "hello"; print(temp); return 0; }
source to share
The reason for this section in [over.ics.rank] / 3 where this case is explicitly addressed:
Standard conversion sequence
S1
is a better conversion sequence than standard conversion sequenceS2
if
[...]
-S1
andS2
are reference bindings (8.5.3) and the types to which the references refer are of the same type, except for the top-level cv qualifiers , and of the type to which the character-initialized referenceS2
has more CV than the type to which the character-initialized reference belongsS1
.
S1
corresponds to the second overload, and S2
- to the first.
What is the reason it calls the function without
const
You always try to choose the most specialized thing. This is the case with overload resolution in the same way as with partial ordering of function templates. The second overload is more specialized than the first, because the first can be called with arguments that the second cannot be called โ that's the main reason for this rule.
source to share
Overloading is done by matching the types of the arguments, including qualifiers. In your case, it temp
is of type std::string
not const std::string
. You only initialized it with a literal constant, it is not a constant.
Consider the following:
std::string temp( "hello" ) ;
print(temp); // hello
print( std::string("hello") ) ; // consthello
print( "hello" ) ; // consthello
print( static_cast<const std::string>(temp) ) ; // consthello
const std::string temp2( "hello" ) ;
print(temp2); // consthello
If you want to remove the non-constant version, all three will invoke the remaining constant overload. In this example, only the const version is actually needed (and preferably) since neither version modifies the string object.
If, on the other hand, you removed the non-const version, there was no function matching any other than the first example above, and the build failed. That is, a non-const object can be safely passed as a const argument, but a const object cannot be passed as a non-const argument, because the function does not "promise" not to modify the object. You can force const to a non-const argument with const_cast
, as in:
const std::string temp2("hello") ;
print( const_cast<std::string&>(temp2) ) ; // hello
But if print()
tried to modify the object, in that case the results are undefined, so consider practice as unsafe.
Creating a const argument indicates intent, allows the compiler to issue diagnostics if code tries to modify an object or pass it using a non-const argument to some other function. It can also potentially provide optimization opportunities for the compiler.
source to share