http://bannalia.blogspot.com/2023/08/user-defined-class-qualifiers-in-c23.html Bannalia: trivial notes on themes diverse Friday, August 18, 2023 User-defined class qualifiers in C++23 It is generally known that type qualifiers (such as const and volatile in C++) can be regarded as a form of subtyping: for instance, const T is a supertype of T because the interface (available operations) of T are strictly wider than those of const T. Foster et al. call a qualifier q positive if q T is a supertype of T, and negative it if is the other way around. Without real loss of generality, in what follows we only consider negative qualifiers, where q T is a subtype of (extends the interface of) T. C++23 explicit object parameters (coloquially known as "deducing this") allow for a particularly concise and effective realization of user-defined qualifiers for class types beyond what the language provides natively. For instance, this is a syntactically complete implementation of qualifier mut, the dual/inverse of const (not to be confused with mutable): template struct mut: T { using T::T; }; template T& as_const(T& x) { return x;} template T& as_const(mut& x) { return x;} struct X { void foo() {} void bar(this mut&) {} }; int main() { mut x; x.foo(); x.bar(); auto& y = as_const(x); y.foo(); y.bar(); // error: cannot convert argument 1 from 'X' to 'mut &' X& z = x; z.foo(); z.bar(); // error: cannot convert argument 1 from 'X' to 'mut &' } The class X has a regular (generally accessible) member function foo and then bar, which is only accessible to instances of the form mut . Access checking and implicit and explicit conversion between subtype mut and mut work as expected. With some help fom Boost.Mp11, the idiom can be generalized to the case of several qualifiers: #include #include #include template struct access: T { using qualifier_list=boost::mp11::mp_list; using T::T; }; template concept qualified = (boost::mp11::mp_contains< typename std::remove_cvref_t::qualifier_list, Qualifiers>::value && ...); // some qualifiers struct mut; struct synchronized; template concept is_mut = qualified; template concept is_synchronized = qualified; struct X { void foo() {} template void bar(this Self&&) {} template void baz(this Self&&) {} template void qux(this Self&&) requires qualified {} }; int main() { access x; x.foo(); x.bar(); x.baz(); // error: associated constraints are not satisfied x.qux(); // error: associated constraints are not satisfied X y; x.foo(); y.bar(); // error: associated constraints are not satisfied access z; z.bar(); z.baz(); z.qux(); } One difficulty remains, though: int main() { access z; //... access& w=z; // error: cannot convert from // 'access' // to 'access &' } access& converts to T&, but not to access & where Qualifiers2 is a subset of Qualifiers (for the mathematically inclined, qualifiers q[1], ... , q[N] over a type T induce a lattice of subtypes Q T, Q [?] {q[1], ... , q[N]}, ordered by qualifier inclusion). Incurring undefined behavior, we could do the following: template struct access: T { using qualifier_list=boost::mp11::mp_list; using T::T; template operator access&() requires qualified { return reinterpret_cast&>(*this); } }; A more interesting challenge is the following: As laid out, this technique implements syntactic qualifier subtyping, but does not do anything towards enforcing the semantics associated to each qualifier: for instance, synchronized should lock a mutex automatically, and a qualifier associated to some particular invariant should assert it after each invocation to a qualifier-constraied member function. I don't know if this functionality can be more or less easily integrated into the presented framework: feedback on the matter is much welcome. Posted by Joaquin M Lopez Munoz at 6:27 PM # No comments : Post a Comment Older Post Home Subscribe to: Post Comments ( Atom ) About Me My Photo Joaquin M Lopez Munoz View my complete profile Blog Archive * 2023 ( 2 ) + August ( 1 ) o User-defined class qualifiers in C++23 + July ( 1 ) * 2022 ( 5 ) + November ( 1 ) + October ( 1 ) + June ( 1 ) + March ( 1 ) + January ( 1 ) * 2016 ( 6 ) + September ( 2 ) + July ( 1 ) + February ( 1 ) + January ( 2 ) * 2015 ( 11 ) + December ( 1 ) + November ( 1 ) + September ( 1 ) + August ( 1 ) + July ( 1 ) + June ( 4 ) + May ( 1 ) + January ( 1 ) * 2014 ( 15 ) + May ( 4 ) + April ( 3 ) + March ( 4 ) + January ( 4 ) * 2013 ( 10 ) + December ( 2 ) + November ( 4 ) + October ( 4 ) * 2009 ( 4 ) + June ( 1 ) + March ( 3 ) * 2008 ( 77 ) + November ( 7 ) + October ( 8 ) + September ( 8 ) + August ( 2 ) + July ( 8 ) + June ( 8 ) + May ( 7 ) + April ( 7 ) + March ( 7 ) + February ( 7 ) + January ( 8 ) * 2007 ( 21 ) + December ( 7 ) + November ( 8 ) + October ( 6 ) Subscribe via email Your email address: [ ][Go] Subscribe subscribe Subscribe to Bannalia Theme images by merrymoonmary. Powered by Blogger.