This all being said, there are many cases in which the return type of the non-const call can determine the return type of the const call. For example, T& -> T const& or T, some_iterator<T> -> some_iterator<T const> or some_const_iterator<T>. It's easy enough.

But there are edge cases, I hear you say. But there are edge cases everywhere, which is why the power to do this needs to rest in the hands of the developer. At the moment this is done by getting the developer to duplicate code (much of the time). I don't see why we cannot have a way of instructing the compiler to do that for us.

I don't like the template hijacking approach. Especially as we now have auto type parameters and widely reduce our use of templating for members, it'd make more sense to be to have a version of auto for the constness. I'm going to call it "clever" for lack of a better thought.

This keyword tells the compiler to determine if the function could have a const version by replacing any calls and types internal and external to the function body with their const equivalents. It won't be general to begin with, but the body of the const and non const versions is typically the same (to the reader) in many cases that would benefit from this. If inference isn't possible, it's an error.

auto begin() clever{
    return x.blah();

if x.blah is clever auto, it generates a const and non const version if possible, and so on and so forth. If x.blah calls y.begin() which has a const version and a non const version, two versions of x.blah. By extension, two versions of begin() above are created. I don't believe this to be such a controversial idea.

With regard to the wider scope of the original post, I certainly DO believe that the language will benefit from providing easier and more flexible access to constness - among other things, including noexceptness to allow the same code to compile with exceptions enabled or disabled, constexprness (which we kind of sort of have with is_constant_evaluated()).

I don't think hijacking the template syntax will suffice for this. Instead I think that we need to think outside the box - or the angle brackets as the case may be.

On Fri, 4 Oct 2019, 09:27 Andrey Semashev via Std-Proposals, <> wrote:
On 2019-10-04 08:15, Phil Bouchard via Std-Proposals wrote:
> 2. a) Like I was saying before, the need for the "const" overloads on
> the "this" parameter forces us to create redundant code and disregards
> the "volatile" qualifier:
> 2. b) The only solution I can foresee is to add a new "qualifier"
> template token type:
> template <qualifier Q>
>      iterator     end () Q noexcept;

This isn't right. The return type must be iterator or const_iterator,
depending on the method qualification.

There isn't such thing as "qualifier" in C++ in the sense distinct from
a type. IOW, qualifier is always part of a type. If you propose to
introduce qualifiers as a distinct entity, you will have to define how
the shall interact with other parts of the language. Especially, what
parts it will break.

Honestly, I don't find your arguments compelling enough for introducing
qualifiers as a distinct entity.
Std-Proposals mailing list