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.
#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