On Fri, Oct 4, 2019 at 3:27 AM Andrey Semashev via Std-Proposals <std-proposals@lists.isocpp.org> 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:
>
> https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06712.html
>
>
> 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
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

As an alternative to introducing a "qualifier" entity, could we not have const(bool) the way we have noexcept(bool) and in C++20, explicit(bool)? But the bool would need to be deducible. We would also want to make the same change for noexcept.

template <bool c>
auto end() const(c) noexcept -> std::conditional_t<c, const_iterator, iterator>;

--

Here is another example: currently, to implement something like the std::is_function type trait, you need 48 partial specializations but we could cut it down to 6:

template <class F> struct is_function : false_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args...) const(c) volatile(v) noexcept(n)> : true_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args...) const(c) volatile(v) & noexcept(n)> : true_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args...) const(c) volatile(v) && noexcept(n)> : true_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args..., ...) const(c) volatile(v) noexcept(n)> : true_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args..., ...) const(c) volatile(v) & noexcept(n)> : true_type {};

template <class R, class... Args, bool c, bool v, bool n>
struct is_function<R(Args..., ...) const(c) volatile(v) && noexcept(n)> : true_type {};

--

Obviously this would still require some fairly nontrivial changes to the standard, but I think it's less complicated than introducing qualifiers as a new entity, and more usable since it lets you get all the qualifiers you care about separately rather than deducing a "Q" that has all of them (and needs to be somehow decomposed). We might be able to handle the ref-qualifiers in a similar way (syntax to be bikeshedded later).

I'm not sure if there's a point to writing a proposal for this now since P0847 will solve most of the problems this solves plus various others. But in my ideal world, we would have both.

--
Brian Bi