C++ Logo

std-proposals

Advanced search

Re: Template qualifiers

From: Mingxin Wang <mingxwa_at_[hidden]>
Date: Wed, 2 Oct 2019 05:04:36 +0000
> 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_microsoft.com>; 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_fornux.com>
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:06:51