Let's say we have a class A like that described by the OP (i.e. with a const and non-const version of the same member function, named A::fun() const and A::fun() respectively.
The difference between the two versions is that the specification of A::fun() const function is that it will not logically change state the object it is called on, but that A::fun() is permitted to.
If a expression/statement some_object.fun() calls A::fun() const then it will not change the logical state (i.e. value of non-static members that are not specified as mutable) of some_object. (Assuming there is no undefined behaviour present).
Similarly, if the expression some_object.fun() calls A::fun() (the non-const version), then the state of some_object may be logically changed.
Now, we need to look at what the implementation (aka compiler) should do when it encounters an expression of the form some_object.fun(). Since there are both A::fun() const and A::fun(), it is necessary to apply some criteria for the implementation to decide which one to call.
The first - simple - case is that some_object is declared const (or is a const reference to an A).
const A some_object;
some_object.fun();
This declaration expresses an intent, by the programmer, that logical state of some_object will not be changed. The non-const version of fun() is permitted to change the state of some_object, so it is never a valid match for some_object.fun() - if the implementation chooses this, it must then issue a diagnostic (which, among other things, usually means that the code will not compile). All this means that A::fun() const is the only permitted choice in this case.
The second case is that some_object is NOT declared as const.
A some_object;
some_object.fun();
The declaration expresses intent, by the programmer, to permit (or, at least, not disallow) changing the logical state of some_object. Since A has both a const and a non-const version of fun() there are three possible choices that could (notionally) have been enshrined in the standard.
- Prefer to call
A::fun() const over A::fun() (the non-const version). There is no harm in not changing an object for which change is permitted. However, this option also eliminates any circumstances in which the non-const function A::fun() would ever be called. There would therefore be no purpose in permitting a class to have both versions.
- Prefer to call
A::fun() over the A::fun() const. There is no harm in this choice, since there is no harm in changing an object when change is permitted.
- Deem
A::fun() and A::fun() const to be equally good candidate. This introduces ambiguity for the compiler since there are two equally valid alternatives, and no reason to prefer one over the other, so a diagnostic is again required. As for option (1), this also means there are no circumstances in which the non-const function would ever be called, so there is no point in permitting a class to have both versions.
Option (2) above is what the standard requires. It means that there are defined circumstances in which each of A::fun() and A::fun() const may be called (a non-const and a const object respectively) and minimal uncertainty in the choice.
With both options (1) and (3), there is no point in the programmer providing both A::fun() and A::fun() const - or for the standard to even allow the programmer to provide both versions - since there are no circumstances in which the non-const version would ever be called when given a statement or expression of the form some_object.fun(). To introduce either option (1) or (3) there would need to be a (possibly complicated) set of additional clauses in the standard that specify when the non-const version of the function should be called. While the C++ standardisation committee is notable for embracing obscure and complicated rules (possibly excessively) it appears they didn't in this case.