C++ Logo

STD-PROPOSALS

Advanced search

Subject: Re: [std-proposals] Template qualifiers
From: Phil Bouchard (phil_at_[hidden])
Date: 2019-10-01 12:56:26


[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 <http://www.fornux.com>
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://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