C++ Logo

std-proposals

Advanced search

Re: Template qualifiers

From: Phil Bouchard <phil_at_[hidden]>
Date: Wed, 2 Oct 2019 01:11:30 -0400
1. "const" overloads happen all the time in order to keep an identical
qualifier in case your "return * this".

2. Because if you can propagate "constexpr" then you can take full
advantage of reserved compile-time functions.


-- 
*Phil Bouchard*
Founder
C.: (819) 328-4743
Fornux Logo <http://www.fornux.com>
On 10/2/19 1:04 AM, Mingxin Wang wrote:
>
> > 1. Will it be able to deduce the "this" qualifier?
>
> No, but why? I do not think it necessary to have such overloads in a 
> class.
>
> > 2. Can the "constexpr" become a qualifier your way? (Because 
> "constexpr" is just a compile-time "const" that cannot be casted away).
>
> No, but again, why?
>
> The motivation for `qualification_type` and `reference_type` is the 
> PFA, introduced in P0957. However, I do not think the two requirements 
> above are universal programming models that should be supported by the 
> language, unless there are convincing motivating use cases.
>
> *From:*Phil Bouchard <phil_at_[hidden]>
> *Sent:* Wednesday, October 2, 2019 12:39 PM
> *To:* Mingxin Wang <mingxwa_at_[hidden]>; 
> std-proposals_at_[hidden]; Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
> *Subject:* Re: [std-proposals] Template qualifiers
>
> Interesting but:
>
> 1. Will it be able to deduce the "this" qualifier?
>
> struct A
>
> {
>
>     A & get() { return * this; }
>
>     A const & get() const { return * this; }
>
>     A volatile & get() volatile { return * this; }
>
>     A const volatile & get() const volatile { return * this; }
>
> };
>
> 2. Can the "constexpr" become a qualifier your way? (Because 
> "constexpr" is just a compile-time "const" that cannot be casted away).
>
> -- 
>
> *Phil Bouchard*
> Founder
> C.: (819) 328-4743
>
> Fornux Logo 
> <https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.fornux.com&data=02%7C01%7Cmingxwa%40microsoft.com%7Ce7be00b6b79e40c9c7bd08d746f26b46%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055879330054127&sdata=3YoGr3bSSUD5pTF71ZyPExLU%2FGldra1Pn0vRcgqDiaQ%3D&reserved=0>
>
> On 10/1/19 10:25 PM, Mingxin Wang wrote:
>
>     I believe there are certain metaprogramming requirements in
>     qualification & reference computation, and a library solution was
>     already proposed in P0957
>     <https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2019%2Fp0957r2.pdf&data=02%7C01%7Cmingxwa%40microsoft.com%7Ce7be00b6b79e40c9c7bd08d746f26b46%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055879330064138&sdata=CtbGc3%2BfbWD5FtYAh%2FgWCgMHLek66YeE1VYMXV3Ab9Y%3D&reserved=0>(section
>     7.1 & 7.2) to support complex type computation required by the
>     PFA, which is a solution for non-intrusive polymorphism.
>
>     I think there is no need to add a language feature for
>     qualification & reference computation because enumeration + type
>     traits would be sufficient, as proposed in P0957:
>
>     enum class qualification_type
>
>         { none, const_qualified, volatile_qualified, cv_qualified };
>
>     enum class reference_type { lvalue, rvalue };
>
>     template <class T, qualification_type Q> using add_qualification_t
>     = …;
>
>     template <class T> inline constexpr qualification_type
>     qualification_of_v = …;
>
>     template <class T, reference_type R> using add_reference_t = …;
>
>     *From:*Std-Proposals <std-proposals-bounces_at_[hidden]>
>     <mailto:std-proposals-bounces_at_[hidden]>*On Behalf Of *Phil
>     Bouchard via Std-Proposals
>     *Sent:* Wednesday, October 2, 2019 1:56 AM
>     *To:* Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
>     <mailto:arthur.j.odwyer_at_[hidden]>; std-proposals_at_[hidden]
>     <mailto:std-proposals_at_[hidden]>
>     *Cc:* Phil Bouchard <phil_at_[hidden]> <mailto:phil_at_[hidden]>
>     *Subject:* Re: [std-proposals] Template qualifiers
>
>     [I apologize for my mistakes, I wrote the email very quickly]
>
>     2 things here:
>
>     1. "constexpr" would ideally need to be treated like a qualifier.
>     This way it could propagate like cv qualifier.
>
>     template<class U>
>     struct construct {
>         template<class QT, class T = std::remove_cvref_t<QT&&>, class
>     = std::enable_if_t<std::is_same_v<T, U>>>
>         QT&& operator()(node_proxy&, QT&& po) {
>            return T(po);
>         }
>     };
>
>     struct node_proxy {};
>
>     node_proxy __x;
>
>     struct ConstClass
>
>     {
>         constexpr ConstClass() {}
>     };
>
>
>     struct NonConstClass
>
>     {
>         NonConstClass() {}
>     };
>
>     // This will result in:
>     construct<ConstClass>()(__x, ConstClass()); // constexpr expression
>     construct<NonConstClass>()(__x, NonConstClass()); // not a
>     constexpr expression
>
>     2. The "qualifier" template token would be:
>
>     - the only way to qualify the "this" parameter;
>
>     - syntactic sugar:
>
>     template<class T>
>     struct construct {
>         template<qualifier Q1, qualifier Q2>
>         Q1 T&& operator()(node_proxy&, Q1 T&& po) Q2 {
>            return T(po);
>         }
>     };
>
>     // This will result in:
>     construct<ConstClass> c1()
>
>     c1(__x, ConstClass()); // constexpr expression
>
>     construct<NonConstClass> volatile const c2()
>
>     c2(__x, NonConstClass()); // not a constexpr expression from an
>     arbitrary "volatile const" object
>
>     -- 
>
>     *Phil Bouchard*
>     Founder
>     C.: (819) 328-4743
>
>     Fornux Logo
>     <https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.fornux.com&data=02%7C01%7Cmingxwa%40microsoft.com%7Ce7be00b6b79e40c9c7bd08d746f26b46%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055879330064138&sdata=ooR7LW%2FIfKk9mRfe%2Bh6N6gEpUAd9CXMF4%2B%2BmTfoY9bc%3D&reserved=0>
>
>     On 9/30/19 9:51 AM, Arthur O'Dwyer wrote:
>
>         On Sun, Sep 29, 2019 at 4:51 PM Phil Bouchard via
>         Std-Proposals <std-proposals_at_[hidden]
>         <mailto:std-proposals_at_[hidden]>> wrote:
>         >
>         > [Please CC my personal email address in the replies
>         otherwise I'll can't properly follow-up]
>         >
>         > So let's take a better example:
>         >
>         > template <typename T>
>         > struct construct<T> {
>         >     // Let the compiler generate the most efficient code
>         >     template <qualifier Q>
>         >     inline T Q operator()(node_proxy & __y, T Q po) {
>         >         return T(po);
>         >     }
>         > };
>         >
>         > struct ConstClass {
>         >     constexpr ConstClass() {}
>         > };
>         >
>         > struct NonConstClass {
>         >     NonConstClass() {}
>         > };
>         >
>         > // This will result in:
>         > construct<ConstClass>()(ConstClass()); // constexpr expression
>         > construct<NonConstClass>()(NonConstClass()); // not a
>         constexpr expression
>
>         Well, I see two or three factual errors here, plus one or two
>         fundamental errors.
>         1. `construct<ConstClass>()(ConstClass())` will not compile as
>         written, because `operator()` takes two parameters, not one.
>         You didn't provide any argument corresponding to parameter `__y`.
>         2. `construct<ConstClass>()(ConstClass())` will not be a
>         compile-time constant, because you didn't mark `operator()` as
>         constexpr. (Remember, the `constexpr` keyword on a function
>         already means "conditionally constexpr"! You don't need any
>         special tricks to achieve conditional constexpr-ness.)
>
>         3. You wrote `template<typename T> construct<T>` as if it were
>         a partial specialization, but I'm going to assume that was a typo.
>
>         4. An rvalue of type `T` is not convertible to a return type
>         of `T &`, nor to `volatile T &&`. Do you think this is a
>         problem for your code?
>
>         5 (fundamental). You still seem to be assuming that `Q` can
>         deduce as "none." Please, consider the ramifications of
>         permitting a template that can deduce either `foo(const int&
>         i)` or `foo(int i)`. Please understand that that overload set
>         would be irretrievably ambiguous and your template would never
>         be usable.
>
>         6 (fundamental). Do you know about */dangling references?/*
>         What do you think happens to your return type when Q is a
>         reference type?
>
>         So, with the understanding that again your own code fails to
>         achieve what you say it does, I would think that the closest
>         C++17 to this would be
>
>             template<class U>
>
>             struct construct {
>
>                 template<class QT, class T = std::remove_cvref_t
>         <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.cppreference.com%2Fw%2Fcpp%2Ftypes%2Fremove_cvref&data=02%7C01%7Cmingxwa%40microsoft.com%7Ce7be00b6b79e40c9c7bd08d746f26b46%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055879330064138&sdata=k3iLdigJE0hlsVtI%2B8zXX2lL%2FNqLLmK6FTbb%2BB0oYP0%3D&reserved=0><QT&&>,
>         class = std::enable_if_t<std::is_same_v<T, U>>>
>
>                 constexpr QT&& operator()(node_proxy&, QT&& po) {
>
>                     return T(po);
>
>                 }
>
>             };
>
>         Notice that this is valid C++03 too, if you polyfill
>         <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FPolyfill_(programming)&data=02%7C01%7Cmingxwa%40microsoft.com%7Ce7be00b6b79e40c9c7bd08d746f26b46%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055879330074130&sdata=n8spgwwuIApiVmlZHd0PVXR%2F88w183kTuuUf0ybrFHA%3D&reserved=0>
>         the library type-traits — e.g. if you use `typename
>         std::enable_if<B>::type` in place of `std::enable_if_t<B>`.
>
>
>
>
>         > Thus qualifiers would be:
>         [...]
>         > const volatile constexpr
>
>         `constexpr` is not a qualifier.
>
>         –Arthur
>

Received on 2019-10-02 00:13:42