Date: Tue, 10 Mar 2020 22:00:53 -0400
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;
#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-10 21:03:43