C++ Logo

std-proposals

Advanced search

Re: Template qualifiers

From: Phil Bouchard <phil_at_[hidden]>
Date: Wed, 2 Oct 2019 08:46:22 -0400
On 10/2/19 1:27 AM, Mingxin Wang wrote:
>
> > 1. "const" overloads happen all the time in order to keep an identical
> qualifier in case your "return * this".
>
> Why do we need to “return *this” with qualifiers? AFAIK, “return
> *this” is mostly useful in “operator=” and some implementation for the
> “builder” design patter, but they always return lvalue reference
> without a qualifier.
>

Please look at the implementation of libstdc++:

https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06712.html


> > 2. Because if you can propagate "constexpr" then you can take full
> advantage of reserved compile-time functions.
>
> What do you mean by “take full advantage of reserved compile-time
> functions”? I think it would be more convincing and easier for us to
> understand if you could provide any real-world meaningful use cases.
>

Please see the reply to Barry.


> *From:*Phil Bouchard <phil_at_[hidden]>
> *Sent:* Wednesday, October 2, 2019 1:12 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
>
> 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
> <https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.fornux.com&data=02%7C01%7Cmingxwa%40microsoft.com%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982620576&sdata=FWPF%2F22FrnXliEHlB40J8hhee4sRaENqFwwnhNjy9ms%3D&reserved=0>
>
> 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]> <mailto:phil_at_[hidden]>
> *Sent:* Wednesday, October 2, 2019 12:39 PM
> *To:* Mingxin Wang <mingxwa_at_[hidden]>
> <mailto:mingxwa_at_[hidden]>; std-proposals_at_[hidden]
> <mailto:std-proposals_at_[hidden]>; Arthur O'Dwyer
> <arthur.j.odwyer_at_[hidden]> <mailto: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%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982630572&sdata=2N8XrG2EprAboVcpD8TTQRpxw39L%2BGdNMsUYrPRmenE%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%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982630572&sdata=7NGE18QhobFIbsJMKEXWbUBriJFYHxX8O4lE756Ve8o%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%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982640565&sdata=Y9xmkMzCoe%2BPFXMUCd5xsnm3rC2VkOUQnCn7B3qObgQ%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%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982640565&sdata=IoHmC6RSptAZfynlfzDFpxwG5%2BvAzmxT4iRH4ToxVGI%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%7C1ab06195c9d146a1bca408d746f6ff43%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C1%7C637055898982650560&sdata=Xo5fbI%2FX67E2ZptputtLdKd7IAsweN9pWC48XpomrV4%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
>
-- 
*Phil Bouchard*
Founder
C.: (819) 328-4743
Fornux Logo <http://www.fornux.com>

Received on 2019-10-02 07:48:34