Prev: Is it dangerous to pass a temp variable to throw
Next: How can I make a class look like a template with zero arguments?
From: pfultz2 on 21 May 2010 07:09 Now say I build an interface like this: class IInterface { public: virtual void foo() = 0; virtual ~IInterface() {}; }; template<class T> class Box : public virtual IInterface { T * x; public: Box() { } Box(T * x) { this->x = x; } virtual void foo() { x->foo(); } }; class Interface { private: IInterface * x; public: template<class T> Interface(T * x) { this->x = new Box<T>(x); } IInterface & operator*() { return *x; } IInterface * operator-> () { return x; } }; Now say I have two classes like this: class A { public: void foo() { printf("foo is called\n"); } }; class B { }; If I do this: A a; B b; Interface interface1 = &a; //OK Compiles Interface interface2 = &b;//Throws compile error because b does not have a member named foo So i would like to create a trait to query whether i can create an interface from B or not, something like this: bool aHas = has_interface<A>::value; //True bool bHas = has_interface<B>::value; //False Ultimately, I would like to use this for function overloading, something like this: template <class T> typename enable_if<has_interface<T> >::type process(cons T& x) { //Optimize using this interface } template <class T> void process(cons T& x) { //The generic code when this interface doesnt exist } I though maybe i could use SFINAE to do this, but I cant figure out a way to deduce this. Perhaps there is another way to do this. Basically if it throws a compiler error on constructing the interface, i want it to return a false value. Does any have any ideas? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: SG on 22 May 2010 04:07 On 22 Mai, 00:09, pfultz2 wrote: > [...] > Now say I have two classes like this: > > class A > { > public: > void foo() > { > printf("foo is called\n"); > } > }; > > class B > { > }; > > [...] > So i would like to create a trait to query whether [T has a > member function foo or not], something like this: > bool aHas = has_interface<A>::value; //True > bool bHas = has_interface<B>::value; //False > > [...] > I though maybe i could use SFINAE to do this, but I cant figure out a > way to deduce this. Perhaps there is another way to do this. Basically > if it throws a compiler error on constructing the interface, i want it > to return a false value. Does any have any ideas? I'm not sure whether it's possible in C++03. But In C++0x this should work: typedef char one; typedef char (&two)[2]; template<class T> T&& declval(); template<class T> struct has_foo_member { template<class U, class = decltype(declval<U>().foo()) > static one test(U*); static two test(...); static const bool value = sizeof(test(declval<T*>()))==1; }; unless some foo member function is private in which case you'll get a compile-time error anyway. Cheers, SG -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: pfultz2 on 23 May 2010 03:46 On May 22, 3:07 pm, SG <s.gesem...(a)gmail.com> wrote: > On 22 Mai, 00:09, pfultz2 wrote: > > > > > [...] > > Now say I have two classes like this: > > > class A > > { > > public: > > void foo() > > { > > printf("foo is called\n"); > > } > > }; > > > class B > > { > > }; > > > [...] > > So i would like to create a trait to query whether [T has a > > member function foo or not], something like this: > > bool aHas = has_interface<A>::value; //True > > bool bHas = has_interface<B>::value; //False > > > [...] > > I though maybe i could use SFINAE to do this, but I cant figure out a > > way to deduce this. Perhaps there is another way to do this. Basically > > if it throws a compiler error on constructing the interface, i want it > > to return a false value. Does any have any ideas? > > I'm not sure whether it's possible in C++03. But In C++0x this should > work: > > typedef char one; > typedef char (&two)[2]; > > template<class T> T&& declval(); > > template<class T> > struct has_foo_member { > template<class U, class = decltype(declval<U>().foo()) > > static one test(U*); > static two test(...); > static const bool value = sizeof(test(declval<T*>()))==1; > }; > > unless some foo member function is private in which case you'll get a > compile-time error anyway. > > Cheers, > SG Thanks, that works great. Here is how I rewrote it to work in gcc without C++0x extensions: template<class T> T declval(); template<class T> struct has_member_foo { template<class U> class selector { }; template<class U> static char test(U * u, selector<typeof(declval<U>().foo())> * dummy = 0); static long test(...); static const bool value = sizeof(test(declval<T*>()))==1; }; It needs typeof to work, it doesnt work with sizeof. I wonder what the difference is. If I use sizeof it will always return false. Thanks, Paul -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Michael Aaron Safyan on 23 May 2010 03:45
It is possible to use SFINAE to detect if a class has a member function. See: http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |