C++ Logo

STD-PROPOSALS

Advanced search

Subject: Re: [std-proposals] Template qualifiers
From: Arthur O'Dwyer (arthur.j.odwyer_at_[hidden])
Date: 2019-09-30 08:51:20


On Sun, Sep 29, 2019 at 4:51 PM Phil Bouchard via Std-Proposals <
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://en.cppreference.com/w/cpp/types/remove_cvref><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://en.wikipedia.org/wiki/Polyfill_(programming)> 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



STD-PROPOSALS list run by herb.sutter at gmail.com

Standard Proposals Archives on Google Groups