0

I have lots of nodes from CCNode subclasses and some of them have the function ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent). Now my question is if it's possible to check if they own this particular function with SFINAE. I tried to make it work with the help of that thread: Is it possible to write a template to check for a function's existence? but I can't.

Here's what I have:

template <typename T>
class hasMethodCCTouchBegan
{
    typedef char yes;
    typedef long no;

    template <typename C> static yes test( decltype(&C::ccTouchBegan) ) ;
    template <typename C> static no test(...);

public:
    enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};

Honestly I have no clue what to do.

Community
  • 1
  • 1
Southgarden116
  • 311
  • 3
  • 16

2 Answers2

0
template<class C>
decltype(&C::ccTouchBegan, std::true_type())
methodHelper(int);

template<class C>
std::false_type
methodHelper(...);

template<class C>
struct hasMethodCCTouchBegan : decltype(methodHelper<C>(0))
{
};

This won't work if ccTouchBegan is overloaded. If you want to test whether ccTouchBegan can be called with certain arguments then you can change &C::ccTouchBegan to std::declval<C>().ccTouchBegan(std::declval<CCTouch*>(), std::declval<CCEvent*>()).

Simple
  • 13,992
  • 2
  • 47
  • 47
  • Thank you very much for that answer. But now I get errors for example: `Unknown type name 'decltype'` Do i still need template `class hasMethodCCTouchBegan { typedef char one; typedef long two;` before that code you wrote? – Southgarden116 Apr 15 '14 at 09:04
  • `decltype` is a C++11 keyword. I assumed you were using C++11 by your use of it. – Simple Apr 15 '14 at 09:59
0

I personally use (in C++11):

#include <cstdint>

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
    template <typename U>                                                   \
    class traitsName                                                        \
    {                                                                       \
    private:                                                                \
        template<typename T, T> struct helper;                              \
        template<typename T>                                                \
        static std::uint8_t check(helper<signature, &funcName>*);           \
        template<typename T> static std::uint16_t check(...);               \
    public:                                                                 \
        static                                                              \
        constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
    }

// Create your traits:
DEFINE_HAS_SIGNATURE(has_ccTouchBegan, T::ccTouchBegan, bool (T::*)(CCTouch *, CCEvent *));
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I get a bunch of errors at line DEFINE_HAS_SIGNATURE, first thing is `Unknown type name 'constexpr'` – Southgarden116 Apr 15 '14 at 09:14
  • VS doesn't support `constexpr`, so you may replace it by `const` here. – Jarod42 Apr 15 '14 at 09:18
  • Okay, I'm using the default compiler in XCode for C++ Language Dialect & Library. Maybe that's it, but I get other errors in other classes when I change it to C++11. EDIT: Cool that solved that issue. Now I have the error `Expected unqualified-id` at `void (T::)`. Is it correct to implement all this in the header and nothing else? – Southgarden116 Apr 15 '14 at 09:31
  • Sorry, `*` was missing: last parameter should be `void (T::*)(CCTouch *, CCEvent *)` (assuming the method returns `void`). – Jarod42 Apr 15 '14 at 09:46
  • Wow thanks a lot! Now do I only have to use `has_ccTouchBegan` in my main method? For example: `has_ccTouchBegan();` Or is there more to it? – Southgarden116 Apr 15 '14 at 09:51
  • Now, you may use `has_ccTouchBegan::value` in your code, for `static_assert`, tag dispatching or SFINAE for example. – Jarod42 Apr 15 '14 at 09:54
  • I hope that's my last question, because I can't seem to make that work. I use `std::cout << has_ccTouchBegan::value;` in my main and it returns 0 even though I know that CCLayer contains that function. – Southgarden116 Apr 15 '14 at 10:21
  • I got it working, I thought that this function was a void because `ccTouchMoved`, `ccTouchEnded` and `ccTouchCancelled` are voids, only `ccTouchBegan` is a `bool`. Thank you! – Southgarden116 Apr 15 '14 at 11:37