From: Chris Fairles on 20 Jul 2007 16:36 Below is some code illustrating the wrong way to do what I'd like to do. I have a class "A" with function "void f(int,int)" and class "B" without that function. Is there a way to construct a traits-like class, Q, that contains a constant expression (Q<T>::value) that evaluates to true if some class T has the function "void f (int,int)" ? Pretend A and B cannot be changed. You only have Q to work with. struct A { void f (int,int){} }; struct B{}; template <class T,class F=void> struct Q { enum{value=false}; }; template<class T> struct Q<T,void(T::*)(int,int)> { enum{value=true}; }; int main() { if( Q<A>::value ) {cout << "A";} if( !Q<B>::value ){cout << "B";} } I'd like this to output "AB". I've tried playing around with boost::enable_if and boost::function_traits but have not come up with a solution. The above code is a trivial case. The real case is, I'm trying to come up with a "is_serializable" type trait (Q) so that an I/O "write"-like function does something special for non-serializable classes (and just does normal serialization for those that are). Every serializable class has this function defined (as a mem func): template <typename Archive> void serialize(Archive &, const unsigned int); If I could add a typedef to each serializable class, no problem. I could even make a typelist of all serializable classes and use a visitor/enable_if or something but I'd like to consider these last resorts. Thanks for the help, Chris -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: KDroben on 21 Jul 2007 12:34 On 21 juil, 09:36, Chris Fairles <chris.fair...(a)gmail.com> wrote: > Below is some code illustrating the wrong way to do what I'd like to > do. I have a class "A" with function "void f(int,int)" and class "B" > without that function. Is there a way to construct a traits-like > class, Q, that contains a constant expression (Q<T>::value) that > evaluates to true if some class T has the function "void f > (int,int)" ? > > Pretend A and B cannot be changed. You only have Q to work with. > > struct A { > void f (int,int){} > > }; > > struct B{}; > > template <class T,class F=void> > struct Q { > enum{value=false}; > > }; > > template<class T> > struct Q<T,void(T::*)(int,int)> { > enum{value=true}; > > }; > > int main() { > if( Q<A>::value ) {cout << "A";} > if( !Q<B>::value ){cout << "B";} > > } > > I'd like this to output "AB". I've tried playing around with > boost::enable_if and boost::function_traits but have not come up with > a solution. > > The above code is a trivial case. The real case is, I'm trying to come > up with a "is_serializable" type trait (Q) so that an I/O "write"-like > function does something special for non-serializable classes (and just > does normal serialization for those that are). Every serializable > class has this function defined (as a mem func): > template <typename Archive> > void serialize(Archive &, const unsigned int); > > If I could add a typedef to each serializable class, no problem. I > could even make a typelist of all serializable classes and use a > visitor/enable_if or something but I'd like to consider these last > resorts. > > Thanks for the help, > Chris Check this article : http://www.codeproject.com/useritems/Detector.asp I think it covers what you are trying to do. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alp Mestan on 21 Jul 2007 18:21 Chris Fairles wrote: > Below is some code illustrating the wrong way to do what I'd like to > do. I have a class "A" with function "void f(int,int)" and class "B" > without that function. Is there a way to construct a traits-like > class, Q, that contains a constant expression (Q<T>::value) that > evaluates to true if some class T has the function "void f > (int,int)" ? > > Pretend A and B cannot be changed. You only have Q to work with. > > struct A { > void f (int,int){} > }; > > struct B{}; > > template <class T,class F=void> > struct Q { > enum{value=false}; > }; > > template<class T> > struct Q<T,void(T::*)(int,int)> { > enum{value=true}; > }; > > int main() { > if( Q<A>::value ) {cout << "A";} > if( !Q<B>::value ){cout << "B";} > } > > I'd like this to output "AB". I've tried playing around with > boost::enable_if and boost::function_traits but have not come up with > a solution. > > The above code is a trivial case. The real case is, I'm trying to come > up with a "is_serializable" type trait (Q) so that an I/O "write"-like > function does something special for non-serializable classes (and just > does normal serialization for those that are). Every serializable > class has this function defined (as a mem func): > template <typename Archive> > void serialize(Archive &, const unsigned int); > > If I could add a typedef to each serializable class, no problem. I > could even make a typelist of all serializable classes and use a > visitor/enable_if or something but I'd like to consider these last > resorts. > > Thanks for the help, > Chris > > It appears that you must give explicitly what is 'F' in your template, as follows : int main() { if( Q<A,void(A::*)(int,int)>::value ) {cout << "A";} if( !Q<B>::value ){cout << "B";} return 0; } It is normal, because the compiler waits two types. When there isn't any second type given, it considers voice instead. The only way to get what you want is to pass your parameters to a function which would auto-detect (template arguments deduction is for functions only) that the function is a member function of T. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Carl Barron on 21 Jul 2007 18:20 In article <1184979526.199331.181740(a)q75g2000hsh.googlegroups.com>, Chris Fairles <chris.fairles(a)gmail.com> wrote: > Below is some code illustrating the wrong way to do what I'd like to > do. I have a class "A" with function "void f(int,int)" and class "B" > without that function. Is there a way to construct a traits-like > class, Q, that contains a constant expression (Q<T>::value) that > evaluates to true if some class T has the function "void f > (int,int)" ? > > Pretend A and B cannot be changed. You only have Q to work with. > > struct A { > void f (int,int){} > }; > > struct B{}; > > template <class T,class F=void> > struct Q { > enum{value=false}; > }; > > template<class T> > struct Q<T,void(T::*)(int,int)> { > enum{value=true}; > }; > > int main() { > if( Q<A>::value ) {cout << "A";} > if( !Q<B>::value ){cout << "B";} > } > > I'd like this to output "AB". I've tried playing around with > boost::enable_if and boost::function_traits but have not come up with > a solution. > > The above code is a trivial case. The real case is, I'm trying to come > up with a "is_serializable" type trait (Q) so that an I/O "write"-like > function does something special for non-serializable classes (and just > does normal serialization for those that are). Every serializable > class has this function defined (as a mem func): > template <typename Archive> > void serialize(Archive &, const unsigned int); > > If I could add a typedef to each serializable class, no problem. I > could even make a typelist of all serializable classes and use a > visitor/enable_if or something but I'd like to consider these last > resorts. > See boost::mpl template <class T> struct is_serializable:boost::mpl::contains < boost::mpl::vector<types_to_serialize_comma_seperated>, T > { }; this has a nested typedef typedef something type; where something is either boost::mpl::true_ or boost::mpl::false_, with obvious meanings. type also has an operator bool() const, and a static const bool which return /is the boolean value true or false accordingly. so you can overload for boost::mpl::true_ and boost::mpl_false or just add a boolean value that defaults to is_serializable<T>::type::value. template <class T> void my_function(const T &a,bool which=is_serializable<T>::type::value) { check the value of which at runtime. } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Greg Herlihy on 21 Jul 2007 18:21 On Jul 21, 12:36 am, Chris Fairles <chris.fair...(a)gmail.com> wrote: > Below is some code illustrating the wrong way to do what I'd like to > do. I have a class "A" with function "void f(int,int)" and class "B" > without that function. Is there a way to construct a traits-like > class, Q, that contains a constant expression (Q<T>::value) that > evaluates to true if some class T has the function "void f > (int,int)" ? > > Pretend A and B cannot be changed. You only have Q to work with. > > struct A { > void f (int,int){} > > }; > > struct B{}; > > template <class T,class F=void> > struct Q { > enum{value=false}; > > }; > > template<class T> > struct Q<T,void(T::*)(int,int)> { > enum{value=true}; > > }; > > int main() { > if( Q<A>::value ) {cout << "A";} > if( !Q<B>::value ){cout << "B";} > > } > > I'd like this to output "AB". I've tried playing around with > boost::enable_if and boost::function_traits but have not come up with > a solution. How about: #include <iostream> template <class T, void (T::*)(int, int) > struct mf_bind { typedef T type; }; template <class T1, class T2> struct has_f { static const bool value = false; }; template <class T> struct has_f<T, typename mf_bind<T, &T::f>::type> { static const bool value = true; }; template <class T> struct Q { static const bool value = has_f<T, T>::value; }; // A and B test classes struct A { void f (int,int){} }; struct B{}; using std::cout; int main() { if( Q<A>::value ) {cout << "A";} if( !Q<B>::value ){cout << "B";} } Program Output: AB Greg -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: Can I have Pure Virtual Destructor? Next: LinkedHashMap in C++ |