C++ Logo

std-proposals

Advanced search

Re: Template qualifiers

From: Phil Bouchard <phil_at_[hidden]>
Date: Fri, 4 Oct 2019 11:31:05 -0400
I was about to suggest the following [intermediate & incomplete] code:

#include <iostream>

using namespace std;


template <typename T>
     struct StackIteratorBase
     {
         T * next;
     };

template <typename T, bool Const = false, bool Volatile = false>
     struct StackIterator : StackIteratorBase<T>
     {
         using StackIteratorBase<T>::next;

         T * get() { return next; }
     };

template <typename T>
     struct StackIterator<T, true, false> : StackIteratorBase<T>
     {
         using StackIteratorBase<T>::next;

         T const * get() const { return next; }
     };

template <typename T>
     struct StackIterator<T, false, true> : StackIteratorBase<T>
     {
         using StackIteratorBase<T>::next;

         T volatile * get() volatile { return next; }
     };

template <typename T>
     struct StackIterator<T, true, true> : StackIteratorBase<T>
     {
         using StackIteratorBase<T>::next;

         T const volatile * get() const volatile { return next; }
     };

int main()
{
     StackIterator<int> i;

     cout << i.get() << endl;

     return 0;
}

But Brian came up with a better syntax.

Personally I'm not sure about P0847
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0847r2.html#name-lookup-candidate-functions),
because it seems to apply to "this" only whereas my goal is to stay
generic, extensible and use a pretty syntax as much as possible.


-- 
*Phil Bouchard*
Founder
C.: (819) 328-4743
Fornux Logo <http://www.fornux.com>
On 10/4/19 1:15 AM, Phil Bouchard wrote:
>
> 2. a) Like I was saying before, the need for the "const" overloads on 
> the "this" parameter forces us to create redundant code and disregards 
> the "volatile" qualifier:
>
> https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06712.html
>
>
> 2. b) The only solution I can foresee is to add a new "qualifier" 
> template token type:
>
> template <qualifier Q>
>
>     iterator     end () Q noexcept;
>
> template <qualifier Q>
>
>     Q T &     front () Q noexcept;
>
>
> 2. c) It is also a much cleaner syntax for other use cases:
>
> 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>>>
>                 constexpr QT&& operator()(node_proxy&, QT&& po)
>
>                 {
>                     return T(po);
>                 }
>     };
>
> We can use instead this much cleaner alternative:
>
> template<class T>
>     struct construct
>
>     {
>         template<qualifier Q>
>                 constexpr Q T&& operator()(node_proxy&, Q T&& po)
>
>                 {
>                     return T(po);
>                 }
>     };
>
> And if "constexpr" becomes a qualifier then simply:
>
> template<class T>
>     struct construct
>
>     {
>         template<qualifier Q>
>                 Q T&& operator()(node_proxy&, Q T&& po)
>
>                 {
>                     return T(po);
>                 }
>     };
>
>
> Thanks,
>
> -- 
>
> *Phil Bouchard*
> Founder
> C.: (819) 328-4743
>
> Fornux Logo <http://www.fornux.com>
>
>
> On 10/3/19 4:07 PM, Arthur O'Dwyer wrote:
>> On Thu, Oct 3, 2019 at 12:26 AM Phil Bouchard <phil_at_[hidden] 
>> <mailto:phil_at_[hidden]>> wrote:
>>
>>     Verdict?
>>
>>
>> Phil, you should pause and try to come up with a motivating example 
>> for the feature you claim to want.
>> Once you have a motivating example, the next step would be to look at 
>> what would be the best way to solve it. Maybe there's even a better 
>> way than what you originally proposed as a feature!
>> That is, start with a problem, and then propose a solution for the 
>> problem. If (by thinking) you end up realizing that you don't have a 
>> problem after all, that's actually a /good/ thing.
>>
>> You do need to /*slow down and think*/ about your examples. Here's 
>> your latest one:
>>
>>     template <typename T>
>>     struct construct
>>     {
>>         T operator () (node_proxy &, T && t) { return T(t); } // will 
>> lose constexpr
>>     };
>>
>> And here's the perfectly valid C++11 code that solves your stated 
>> problem:
>>
>>     template <typename T>
>>     struct construct
>>     {
>> *constexpr* T operator () (node_proxy &, T && t) { return T(t); } // 
>> no longer loses constexpr
>>     };
>> See also: http://sscce.org
>>
>> –Arthur
>>

Received on 2019-10-04 10:33:18