C++ Logo

std-proposals

Advanced search

Re: Template qualifiers

From: Phil Bouchard <phil_at_[hidden]>
Date: Wed, 2 Oct 2019 00:38:46 -0400
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 <http://www.fornux.com>
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 
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0957r2.pdf> 
> (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]> *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]>; 
> std-proposals_at_[hidden]
> *Cc:* Phil Bouchard <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%7Ca157e7a636594646b5ac08d74698b184%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637055493938879119&sdata=hlPFE233BbGwXUNiSfLRE0ToVkryhyG0TpnR6NHab18%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%7Ca157e7a636594646b5ac08d74698b184%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637055493938889127&sdata=eUUuf%2BDhnpfpGvQ6NR7vZ1JUFNHXPYKujJqnmmLDq4M%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%7Ca157e7a636594646b5ac08d74698b184%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637055493938889127&sdata=R92akOUMx%2BoS%2BnIafUz%2Fmz02AbnaMtnAoZD%2FnnMzhXg%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-01 23:40:58