As many other people have answered, from an API perspective, the following are all equivalent, and are equal for overload-resolution:
void foo( int );
void foo( const int );
But a better question is whether or not this provides any semantic meaning to a consumer of this API, or whether it provides any enforcement of good behaviours from a developer of the implementation.
Without any well-defined developer coding guidelines that expressly define this, const
scalar arguments have no readily obvious semantic meaning.
From a consumer:
const int
does not change your input. It can still be a literal, or it can be from another variable (both const
or non-const
)
From a developer:
const int
imposes a restriction on a local copy of a variable (in this case, a function argument). This just means to modify the argument, you take another copy of the variable and modify it instead.
When calling a function that accepts an argument by-value, a copy is made of that argument on the stack for the called function. This gives the function a local copy of the argument for its entire scope that can then be modified, used for calculations, etc -- without affecting the original input passed into the call. Effectively, this provides a local variable argument of its input.
By marking the argument as const
, it simply means that this copy cannot be modified; but it does not prohibit the developer from copying it and making modifications to this copy. Since this was a copy from the start, it does not enforce all that much from inside the implementation -- and ultimately doesn't make much difference from the consumer's perspective.
This is in contrast to passing by reference, wherein a reference to int&
is semantically different from const int&
. The former is capable of mutating its input; the latter is only capable of observing the input (provided the implementation doesn't const_cast
the const
-ness away -- but lets ignore this possibility); thus, const
-ness on references have an implied semantic meaning.
It does not provide much benefit being in the public API; and (imo) introduces unnecessary restrictions into the implementation. As an arbitrary, contrived example -- a simple function like:
void do_n_times( int n )
{
while( n-- > 0 ) {
// do something n times
}
}
would now have to be written using an unnecessary copy:
void do_n_times( const int n )
{
auto n_copy = n;
while( n_copy-- > 0 ) {
// do something n times
}
}
Regardless of whether const
scalars are used in the public API, one key thing is to be consistent with the design. If the API randomly switches between using const
scalar arguments to using non-const
scalars, then it can cause confusion as to whether there is meant to be any implied meaning to the consumer.
TL;DR: const
scalar types in a public API don't convey semantic meaning unless explicitly defined by your own guidelines for your domain.