Date: Wed, 11 Mar 2020 07:34:31 -0400
To go back to the generic template 'this', here is another useful
example that centralizes mathematical operations:
// What the user sees:
struct A
{
int value;
A(A const & a) : value(a.value)
{
}
A & operator += (A const & a)
{
value += a.value;
return * this;
}
A & operator -= (A const & a)
{
value -= a.value;
return * this;
}
A & operator *= (A const & a)
{
value *= a.value;
return * this;
}
A & operator /= (A const & a)
{
value /= a.value;
return * this;
}
A & operator = (A const & a) = generic; // the 'generic' keyword
could be used to hint the compiler of our intents
A operator + (A const & a) const = generic;
A operator - (A const & a) const = generic;
A operator * (A const & a) const = generic;
A operator / (A const & a) const = generic;
};
// Some "generic" header:
template <typename Class>
Class & Class::operator = (Class const & c)
{
~Class();
new (this) Class(c);
return * this;
}
template <typename Class>
Class Class::operator + (Class const & c) const
{
Class r(* this);
r += c;
return r;
}
template <typename Class>
Class Class::operator - (Class const & c) const
{
Class r(* this);
r -= c;
return r;
}
template <typename Class>
Class Class::operator * (Class const & c) const
{
Class r(* this);
r *= c;
return r;
}
template <typename Class>
Class Class::operator / (Class const & c) const
{
Class r(* this);
r /= c;
return r;
}
example that centralizes mathematical operations:
// What the user sees:
struct A
{
int value;
A(A const & a) : value(a.value)
{
}
A & operator += (A const & a)
{
value += a.value;
return * this;
}
A & operator -= (A const & a)
{
value -= a.value;
return * this;
}
A & operator *= (A const & a)
{
value *= a.value;
return * this;
}
A & operator /= (A const & a)
{
value /= a.value;
return * this;
}
A & operator = (A const & a) = generic; // the 'generic' keyword
could be used to hint the compiler of our intents
A operator + (A const & a) const = generic;
A operator - (A const & a) const = generic;
A operator * (A const & a) const = generic;
A operator / (A const & a) const = generic;
};
// Some "generic" header:
template <typename Class>
Class & Class::operator = (Class const & c)
{
~Class();
new (this) Class(c);
return * this;
}
template <typename Class>
Class Class::operator + (Class const & c) const
{
Class r(* this);
r += c;
return r;
}
template <typename Class>
Class Class::operator - (Class const & c) const
{
Class r(* this);
r -= c;
return r;
}
template <typename Class>
Class Class::operator * (Class const & c) const
{
Class r(* this);
r *= c;
return r;
}
template <typename Class>
Class Class::operator / (Class const & c) const
{
Class r(* this);
r /= c;
return r;
}
-- *Phil Bouchard* Founder C.: (819) 328-4743 Fornux Logo <http://www.fornux.com> On 3/10/20 10:00 PM, Phil Bouchard wrote: > > Regarding the for_each_member() functor, here is a possible > implementation: > > #include <iostream> > > using namespace std; > > > template <typename F> > inline ostream & print(F && f, char const * n, ostream & out) > { > out << n; > > return out; > } > > template <typename F> > inline ostream & print(F && f, char const * n, char const * t, > ostream & out) > { > out << n << " = " << t; > > return out; > } > > template <typename F> > inline ostream & print(F && f, char const * n, int const t, > ostream & out) > { > out << n << " = " << t; > > return out; > } > > template <typename F, typename T> > inline ostream & print(F && f, char const * n, T const & t, > ostream & out) > { > f.begin(n, t, out); > typename T::template for_each_member<F, > ostream>()(forward<F>(f), t, out); > f.end(n, t, out); > > return out; > } > > > // New "pretty" header: > > struct pretty > { > size_t s; > char c; > > pretty(size_t s = 0, char c = '\t') : s(s), c(c) > { > } > > ostream & indent(ostream & out) > { > for (size_t i = 0; i < s; ++ i) > out << c; > > return out; > } > > template <typename T> > void begin(char const * n, T const & t, ostream & out) > { > out << n << " = " << endl; > indent(out) << "{" << endl; > > ++ s; > } > > template <typename T> > void end(char const * n, T const & t, ostream & out) > { > -- s; > > indent(out) << "}"; > } > > template <typename T> > void operator () (char const * n, T const & t, size_t i, > size_t e, ostream & out) > { > indent(out); > > print(* this, n, t, out); > > if (i != e - 1) > out << ','; > > out << endl; > } > }; > > > struct sql > { > template <typename T> > void begin(char const * n, T const & t, ostream & out) const > { > out << "SELECT "; > } > > template <typename T> > void end(char const * n, T const & t, ostream & out) const > { > out << " FROM " << n << ";"; > } > > template <typename T> > void operator () (char const * n, T const & t, size_t i, > size_t e, ostream & out) const > { > print(* this, n, out); > > if (i != e - 1) > out << ", "; > } > }; > > > // Usage example: > > struct A > { > int a = 0; > int b = 1; > int c = 2; > > // Generated by the compiler: > template <typename F, typename ...T> > struct for_each_member > { > void operator () (F && f, A const & a, T & ...t) > { > f("a", a.a, 0, 3, t...); > f("b", a.b, 1, 3, t...); > f("c", a.c, 2, 3, t...); > } > }; > }; > > > struct B > { > int d = 0; > int e = 1; > A f = A(); > > // Generated by the compiler: > template <typename F, typename ...T> > struct for_each_member > { > void operator () (F && f, B const & b, T & ...t) > { > f("d", b.d, 0, 3, t...); > f("e", b.e, 1, 3, t...); > f("f", b.f, 2, 3, t...); > } > }; > }; > > > int main() > { > B b; > > cout << "Pretty print:" << endl; > print(pretty(), "b", b, cout) << endl; > cout << endl; > > cout << "SQL print:" << endl; > print(sql(), "b", b, cout) << endl; > } > > > Outputs: > > Pretty print: > b = > { > d = 0, > e = 1, > f = > { > a = 0, > b = 1, > c = 2 > } > } > > SQL print: > SELECT d, e, f FROM b; > > -- > > *Phil Bouchard* > Founder > C.: (819) 328-4743 > > Fornux Logo <http://www.fornux.com> > > > On 3/10/20 1:56 PM, Phil Bouchard wrote: >> Even better: for_each_member<> should be nested inside their >> respective class (i.e. typename A::for_each_member<>), this way we >> won’t pollute the global namespace at all and have a million error >> messages when something goes wrong. >> >> Also we could have: >> ...::for_each_member<> >> ...::for_each_public_member<> >> ...::for_each_private_member<> >> ...::for_each_protected_member<> >> >> -- >> >> *Phil Bouchard* >> Founder >> C.: (819) 328-4743 <tel:(819)%20328-4743> >> >> Fornux Logo <http://www.fornux.com/> >> >> On Mar 10, 2020, at 8:50 AM, Phil Bouchard <phil_at_[hidden] >> <mailto:phil_at_[hidden]>> wrote: >> >>> Here are little corrections: >>> >>> #include <iostream> >>> #include <functional> >>> >>> using namespace std; >>> >>> >>> // Compiler internal: >>> >>> template <typename F, typename ...T> >>> struct for_each_member; >>> >>> template <typename F, typename ...T> >>> inline void make_for_each_member(F && f, T && ...t) >>> { >>> for_each_member<F, T...>()(forward<F>(f), forward<T>(t)...); >>> } >>> >>> >>> // New "pretty" header: >>> >>> struct pretty >>> { >>> size_t n; >>> >>> pretty(size_t n = 0):n(n) {} >>> >>> ostream & indent(size_t n, ostream & out) >>> { >>> for (size_t i = 0; i < n * 4; ++ i) >>> out << ' '; >>> >>> return out; >>> } >>> >>> template <typename T> >>> void operator () (T const & t, size_t i, size_t e, size_t n, >>> ostream & out) >>> { >>> if (i == 0) >>> indent(n, out) << '{' << endl; >>> >>> indent(n + 1, out) << t; >>> >>> if (i != e - 1) >>> out << ','; >>> >>> out << endl; >>> >>> if (i == e - 1) >>> indent(n, out) << '}'; >>> } >>> }; >>> >>> // New "print" header: >>> >>> template <typename T, typename F> >>> inline ostream & T::print(F && f, ostream & out) >>> { >>> make_for_each_member(f, * this, cout); >>> >>> return out; >>> } >>> >>> >>> // Usage example: >>> >>> struct A >>> { >>> int a = 0, b = 1, c = 2; >>> >>> // Capabilities: >>> template <typename F> >>> ostream & print(F && f, ostream & out); // only a >>> declaration needed if "print" header included >>> }; >>> >>> >>> // Generated by the compiler: >>> >>> template <typename F, typename ...T> >>> struct for_each_member<F, A, T...> >>> { >>> void operator () (F && f, A && a, T && ...t) >>> { >>> f(forward<decltype(a.a)>(a.a), 0, 3, forward<T>(t)...); >>> f(forward<decltype(a.b)>(a.b), 1, 3, forward<T>(t)...); >>> f(forward<decltype(a.c)>(a.c), 2, 3, forward<T>(t)...); >>> } >>> }; >>> >>> >>> int main() >>> { >>> A a; >>> >>> a.print(pretty(), cout) << endl; >>> a.print(binary(), cout) << endl; >>> a.print(sql(), cout) << endl; >>> } >>> >>> >>> -- >>> >>> *Phil Bouchard* >>> Founder >>> C.: (819) 328-4743 >>> >>> Fornux Logo <http://www.fornux.com> >>> >>> >>> On 3/10/20 12:03 AM, Phil Bouchard wrote: >>>> >>>> Here's a prettier example, without the template template functor: >>>> >>>> #include <iostream> >>>> #include <functional> >>>> >>>> using namespace std; >>>> >>>> >>>> // Compiler internal: >>>> >>>> template <typename F, typename ...T> >>>> struct for_each_member; >>>> >>>> template <typename F, typename ...T> >>>> inline void make_for_each_member(F && f, T && ...t) >>>> { >>>> for_each_member<F, T...>()(forward<F>(f), forward<T>(t)...); >>>> } >>>> >>>> >>>> // New "pretty_print" header: >>>> >>>> struct pretty_print >>>> { >>>> size_t n; >>>> >>>> pretty_print(size_t n = 0):n(n) {} >>>> >>>> ostream & indent(size_t n, ostream & out) >>>> { >>>> for (size_t i = 0; i < n * 4; ++ i) >>>> out << ' '; >>>> >>>> return out; >>>> } >>>> >>>> template <typename T> >>>> void operator () (T const & t, size_t i, size_t e, size_t >>>> n, ostream & out) >>>> { >>>> if (i == 0) >>>> indent(n, out) << '{' << endl; >>>> >>>> indent(n + 1, out) << t; >>>> >>>> if (i != e - 1) >>>> out << ','; >>>> >>>> out << endl; >>>> >>>> if (i == e - 1) >>>> indent(n, out) << '}'; >>>> } >>>> }; >>>> >>>> template <typename T> >>>> inline ostream & T::pretty_print(size_t n, ostream & out) >>>> { >>>> pretty_print f(n); >>>> >>>> make_for_each_member<pretty_print>(f, T(), cout); >>>> >>>> return out; >>>> } >>>> >>>> >>>> // Usage example: >>>> >>>> struct A >>>> { >>>> int a = 0, b = 1, c = 2; >>>> >>>> // Capabilities: >>>> ostream & pretty_print(size_t n, ostream & out); // only a >>>> declaration needed if "pretty_print" header included >>>> ostream & binary_print(ostream & out); // same here >>>> ostream & sql_print(ostream & out); // same >>>> }; >>>> >>>> >>>> // Generated by the compiler: >>>> >>>> template <typename F, typename ...T> >>>> struct for_each_member<F, A, T...> >>>> { >>>> void operator () (F && f, A && a, T && ...t) >>>> { >>>> f(forward<decltype(a.a)>(a.a), 0, 3, forward<T>(t)...); >>>> f(forward<decltype(a.b)>(a.b), 1, 3, forward<T>(t)...); >>>> f(forward<decltype(a.c)>(a.c), 2, 3, forward<T>(t)...); >>>> } >>>> }; >>>> >>>> >>>> int main() >>>> { >>>> A a; >>>> >>>> a.pretty_print(0, cout) << endl; >>>> } >>>> >>>> -- >>>> >>>> *Phil Bouchard* >>>> Founder >>>> C.: (819) 328-4743 >>>> >>>> Fornux Logo <http://www.fornux.com> >>>> >>>> >>>> On 3/9/20 8:44 PM, Phil Bouchard wrote: >>>>> >>>>> Here is a clean usage example: >>>>> >>>>> #include <iostream> >>>>> #include <functional> >>>>> >>>>> using namespace std; >>>>> >>>>> >>>>> // Compiler internal: >>>>> >>>>> template <template <typename> class F, typename ...T> // note the >>>>> usage of the necessary template template parameter >>>>> struct for_each_member; >>>>> >>>>> template <template <typename> class F, typename ...T> >>>>> inline void make_for_each_member(T && ...t) >>>>> { >>>>> for_each_member<F, T...>()(forward<T>(t)...); >>>>> } >>>>> >>>>> >>>>> // New "pretty_print" header: >>>>> >>>>> template <typename T> >>>>> struct pretty_print >>>>> { >>>>> ostream & indent(size_t n, ostream & out) >>>>> { >>>>> for (size_t i = 0; i < n * 4; ++ i) >>>>> out << ' '; >>>>> >>>>> return out; >>>>> } >>>>> >>>>> void operator () (T const & t, size_t i, size_t e, size_t >>>>> n, ostream & out) >>>>> { >>>>> if (i == 0) >>>>> indent(n, out) << '{' << endl; >>>>> >>>>> indent(n + 1, out) << t; >>>>> >>>>> if (i != e - 1) >>>>> out << ','; >>>>> >>>>> out << endl; >>>>> >>>>> if (i == e - 1) >>>>> indent(n, out) << '}'; >>>>> } >>>>> }; >>>>> >>>>> template <typename T> >>>>> inline ostream & T::pretty_print(ostream & out) >>>>> { >>>>> size_t indent = 0; >>>>> >>>>> make_for_each_member<pretty_print>(T(), indent, cout); >>>>> >>>>> return out; >>>>> } >>>>> >>>>> >>>>> // Usage example (what the user will only see): >>>>> >>>>> struct A >>>>> { >>>>> int a = 0, b = 1, c = 2; >>>>> >>>>> ostream & pretty_print(ostream & out); // only a declaration >>>>> needed if "pretty_print" header included >>>>> }; >>>>> >>>>> >>>>> // Generated by the compiler: >>>>> >>>>> template <template <typename> class F, typename ...T> >>>>> struct for_each_member<F, A, T...> >>>>> { >>>>> void operator () (A && a, T && ...t) >>>>> { >>>>> F<decltype(a.a)>()(forward<decltype(a.a)>(a.a), 0, 3, >>>>> forward<T>(t)...); >>>>> F<decltype(a.b)>()(forward<decltype(a.b)>(a.b), 1, 3, >>>>> forward<T>(t)...); >>>>> F<decltype(a.c)>()(forward<decltype(a.c)>(a.c), 2, 3, >>>>> forward<T>(t)...); >>>>> } >>>>> }; >>>>> >>>>> >>>>> int main() >>>>> { >>>>> A a; >>>>> >>>>> a.pretty_print(cout) << endl; >>>>> } >>>>> >>>>> >>>>> Other applications of for_each_member() can be: >>>>> >>>>> - comparisons, >>>>> >>>>> - changing properties of filtered mutable member variables, >>>>> >>>>> - generic debug functions changed on-the-fly at one place only, >>>>> >>>>> - easily apply textual and binary I/O operations to huge structures, >>>>> >>>>> - easily apply database operations to huge structures, >>>>> >>>>> - automate the mapping of structures to a user-interface generator, >>>>> >>>>> - ... >>>>> >>>>> >>>>> -- >>>>> >>>>> *Phil Bouchard* >>>>> Founder >>>>> C.: (819) 328-4743 >>>>> >>>>> Fornux Logo <http://www.fornux.com> >>>>> >>>>> >>>>> On 3/9/20 10:56 AM, Phil Bouchard wrote: >>>>>> ... Also we could limit generic ‘this’ overloads to specific >>>>>> namespaces: >>>>>> >>>>>> template <typename Class> >>>>>> ostream & boost::detail::Class::operator << (ostream & out) { >>>>>> ... } >>>>>> >>>>>> -- >>>>>> >>>>>> *Phil Bouchard* >>>>>> Founder >>>>>> C.: (819) 328-4743 <tel:(819)%20328-4743> >>>>>> >>>>>> Fornux Logo <http://www.fornux.com/> >>>>>> >>>>>> On Mar 8, 2020, at 7:36 PM, Phil Bouchard <phil_at_[hidden] >>>>>> <mailto:phil_at_[hidden]>> wrote: >>>>>> >>>>>>> ... And only the classes with the proper declarations would take >>>>>>> advantage of the generic template 'this': >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> >>>>>>> *Phil Bouchard* >>>>>>> Founder >>>>>>> C.: (819) 328-4743 >>>>>>> >>>>>>> Fornux Logo <http://www.fornux.com> >>>>>>> >>>>>>> >>>>>>> On 3/8/20 7:34 PM, Phil Bouchard wrote: >>>>>>>> >>>>>>>> What I have in mind is to clean up the dispatch fiasco that is >>>>>>>> done with either the constructors or the cast operator right >>>>>>>> now. Conversions, comparisons, ... should be simplified as >>>>>>>> well. For example: >>>>>>>> >>>>>>>> struct X >>>>>>>> >>>>>>>> { >>>>>>>> >>>>>>>> int value; >>>>>>>> >>>>>>>> >>>>>>>> template <typename T> >>>>>>>> >>>>>>>> X(T const & T); >>>>>>>> >>>>>>>> template <typename T> >>>>>>>> >>>>>>>> operator T (); >>>>>>>> >>>>>>>> }; >>>>>>>> >>>>>>>> struct Y >>>>>>>> >>>>>>>> { >>>>>>>> >>>>>>>> int value; >>>>>>>> >>>>>>>> >>>>>>>> template <typename T> >>>>>>>> >>>>>>>> Y(T const & T); >>>>>>>> >>>>>>>> template <typename T> >>>>>>>> >>>>>>>> operator T (); >>>>>>>> >>>>>>>> }; >>>>>>>> >>>>>>>> template <typename Class, typename T> >>>>>>>> >>>>>>>> inline Class::operator T () { return T(* this); } // >>>>>>>> generic constructor wrapper >>>>>>>> >>>>>>>> template <typename Class, typename T> >>>>>>>> >>>>>>>> inline Class::Class(T const &t) { value = t.value; } // >>>>>>>> cast operation really done here >>>>>>>> >>>>>>>> >>>>>>>> And normal specializations here: >>>>>>>> >>>>>>>> template <typename T> >>>>>>>> >>>>>>>> inline X::X(T const &t) { value = t.value; } // specialized >>>>>>>> cast operation done here >>>>>>>> >>>>>>>> >>>>>>>> Also if we had a way to iterate all members (which would be >>>>>>>> another important proposal) then we could also have a generic >>>>>>>> "operator <<" as well: >>>>>>>> >>>>>>>> template <typename Class> >>>>>>>> >>>>>>>> ostream & Class::operator << (ostream & out) >>>>>>>> >>>>>>>> { >>>>>>>> >>>>>>>> for (member_iterator<Class> i = >>>>>>>> member_iterator<Class>::begin(); i != >>>>>>>> member_iterator<Class>::end(); ++ i) >>>>>>>> >>>>>>>> { >>>>>>>> >>>>>>>> if (i != member_iterator<Class>::begin()) >>>>>>>> >>>>>>>> out << ", "; >>>>>>>> >>>>>>>> out << this->*i; >>>>>>>> >>>>>>>> } >>>>>>>> >>>>>>>> return out; >>>>>>>> >>>>>>>> } >>>>>>>> >>>>>>>> The aforementioned should also remove the need for these global >>>>>>>> friend function overloads. >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> >>>>>>>> *Phil Bouchard* >>>>>>>> Founder >>>>>>>> C.: (819) 328-4743 >>>>>>>> >>>>>>>> Fornux Logo <http://www.fornux.com> >>>>>>>> >>>>>>>> >>>>>>>> On 3/8/20 6:03 PM, Jake Arkinstall wrote: >>>>>>>>> For me, this approach has some merits, but this particular >>>>>>>>> example is something that, to me, makes much more sense as a >>>>>>>>> free function. >>>>>>>>> >>>>>>>>> Do you have further examples? >>>>>>>>> >>>>>>>>> On Sun, 8 Mar 2020, 21:55 Phil Bouchard via Std-Proposals, >>>>>>>>> <std-proposals_at_[hidden] >>>>>>>>> <mailto:std-proposals_at_[hidden]>> wrote: >>>>>>>>> >>>>>>>>> Well I believe a proposal should be open for debate, just >>>>>>>>> like a thesis. >>>>>>>>> >>>>>>>>> We both agree these overloads should be simplified but we >>>>>>>>> disagree on the syntax. >>>>>>>>> >>>>>>>>> I saw the recursive lambda thing and I think I already >>>>>>>>> talked to you before regarding CV overloads but we were >>>>>>>>> proposing the following syntax: >>>>>>>>> >>>>>>>>> struct A >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> template <bool BC> >>>>>>>>> >>>>>>>>> void foo() bool<BC> >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> }; >>>>>>>>> >>>>>>>>> And regarding the this generic overloading I still believe >>>>>>>>> the following syntax is cleaner: >>>>>>>>> >>>>>>>>> struct A >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> template <typename T> >>>>>>>>> >>>>>>>>> bool compare(T const &); >>>>>>>>> >>>>>>>>> }; >>>>>>>>> >>>>>>>>> template <typename C, typename T> >>>>>>>>> >>>>>>>>> void C::compare(C const &) >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> ... >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> Because with your syntax I could technically reassign "self": >>>>>>>>> >>>>>>>>> struct A >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> template <typename C, typename T> >>>>>>>>> >>>>>>>>> bool compare(this C & c, T const &); >>>>>>>>> >>>>>>>>> }; >>>>>>>>> >>>>>>>>> template <typename C, typename T> >>>>>>>>> >>>>>>>>> bool C::compare(this C & c, T const &) // redundant C here >>>>>>>>> >>>>>>>>> { >>>>>>>>> >>>>>>>>> static C sc = C(); >>>>>>>>> >>>>>>>>> c = sc; // in theory we could do this unless you >>>>>>>>> patch the compilers with a new error for that specific case >>>>>>>>> >>>>>>>>> } >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> >>>>>>>>> *Phil Bouchard* >>>>>>>>> Founder >>>>>>>>> C.: (819) 328-4743 >>>>>>>>> >>>>>>>>> Fornux Logo <http://www.fornux.com> >>>>>>>>> >>>>>>>>> >>>>>>>>> On 3/8/20 5:37 AM, Gašper Ažman wrote: >>>>>>>>>> I meant that you should consider the incremental value of >>>>>>>>>> your proposal over p0847, which is on track for c++23 >>>>>>>>>> unless serious issues crop up >>>>>>>>>> >>>>>>>>>> On Sat, Mar 7, 2020, 19:04 Phil Bouchard <phil_at_[hidden] >>>>>>>>>> <mailto:phil_at_[hidden]>> wrote: >>>>>>>>>> >>>>>>>>>> The syntaxes are way different: >>>>>>>>>> >>>>>>>>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0847r4.html >>>>>>>>>> >>>>>>>>>> In your case the compiler will have to change all of >>>>>>>>>> its rules for the number of parameters "operator" >>>>>>>>>> overloads. For example: >>>>>>>>>> >>>>>>>>>> struct A >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> >>>>>>>>>> int value; >>>>>>>>>> >>>>>>>>>> ... >>>>>>>>>> >>>>>>>>>> template <typename Self> >>>>>>>>>> >>>>>>>>>> bool operator < (this Self && self, A const & >>>>>>>>>> a) // 2 parameters... ok >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> >>>>>>>>>> return self.value < a.value; >>>>>>>>>> >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> bool operator < (A const & a) // 1 >>>>>>>>>> parameter... ok >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> >>>>>>>>>> return value < a.value; >>>>>>>>>> >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> }; >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> >>>>>>>>>> *Phil Bouchard* >>>>>>>>>> Founder >>>>>>>>>> C.: (819) 328-4743 >>>>>>>>>> >>>>>>>>>> Fornux Logo <http://www.fornux.com> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On 3/7/20 1:35 PM, Gašper Ažman wrote: >>>>>>>>>>> P0847 >>>>>>>>>>> >>>>>>>>>>> On Sat, Mar 7, 2020, 18:33 Phil Bouchard via >>>>>>>>>>> Std-Proposals <std-proposals_at_[hidden] >>>>>>>>>>> <mailto:std-proposals_at_[hidden]>> wrote: >>>>>>>>>>> >>>>>>>>>>> Alright, I'm pretty sure this is not implemented >>>>>>>>>>> yet. Suppose you have: >>>>>>>>>>> >>>>>>>>>>> struct A >>>>>>>>>>> >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> int value; >>>>>>>>>>> >>>>>>>>>>> ... >>>>>>>>>>> >>>>>>>>>>> template <typename T> >>>>>>>>>>> >>>>>>>>>>> int compare(T const & t) const; >>>>>>>>>>> >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> struct B >>>>>>>>>>> >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> int value; >>>>>>>>>>> >>>>>>>>>>> ... >>>>>>>>>>> >>>>>>>>>>> template <typename T> >>>>>>>>>>> >>>>>>>>>>> int compare(T const & t) const; >>>>>>>>>>> >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Then a generic way to define the same >>>>>>>>>>> functionality for all classes would be to have a >>>>>>>>>>> "template 'this'": >>>>>>>>>>> >>>>>>>>>>> template <typename C, typename T> >>>>>>>>>>> >>>>>>>>>>> inline int C::compare(T const & t) const >>>>>>>>>>> >>>>>>>>>>> { >>>>>>>>>>> >>>>>>>>>>> return value == t.value ? 0 : value < t.value ? >>>>>>>>>>> -1 : 1; >>>>>>>>>>> >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> (Please include my email address in your replies) >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> >>>>>>>>>>> *Phil Bouchard* >>>>>>>>>>> Founder >>>>>>>>>>> C.: (819) 328-4743 >>>>>>>>>>> >>>>>>>>>>> Fornux Logo <http://www.fornux.com> >>>>>>>>>>> -- >>>>>>>>>>> Std-Proposals mailing list >>>>>>>>>>> Std-Proposals_at_[hidden] >>>>>>>>>>> <mailto:Std-Proposals_at_[hidden]> >>>>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals >>>>>>>>>>> >>>>>>>>> -- >>>>>>>>> Std-Proposals mailing list >>>>>>>>> Std-Proposals_at_[hidden] >>>>>>>>> <mailto:Std-Proposals_at_[hidden]> >>>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals >>>>>>>>>
Received on 2020-03-11 06:37:20