[ create a new paste ] login | about

Link: http://codepad.org/eL0Pe1xZ    [ raw code | output | fork ]

litb - C++, pasted on Jun 17:
#include <string>
#include <iostream>
#include <boost/function.hpp>

namespace detail {
template<typename T> struct IsClassType {
  template<typename U> static char (& is(U *U::*) )[1];
  template<typename U> static char (& is(...) )[2];
  static bool const value = (sizeof is<T>(0) == 1);
};

struct Marker { };
struct Detector { };
template<typename U> struct Detected { };
template<typename U> Detected<U> operator,(Detector, U const&);
template<typename U> char (& operator,(Detected<U>, char(&)[2]) )[2];
char (& operator,(Detected<Marker>, char(&)[2]) )[1];
}

#define IS_CALLABLE(N, ARGS, TNAME)                                     \
  template<typename T,                                                  \
           bool IsClassType = detail::IsClassType<T>::value>            \
  struct TNAME##_hasN {                                                 \
    struct D1 { void N(); };                                            \
    struct D : D1, T { };                                               \
                                                                        \
    template<typename U, U> struct ChT;                                 \
                                                                        \
    template<typename U>                                                \
    static char (& has(ChT<void (D1::*)(), &U::N>*) )[1];               \
                                                                        \
    template<typename U>                                                \
    static char (& has(...) )[2];                                       \
                                                                        \
    static bool const value = (sizeof has<D>(0) == 2);                  \
  };                                                                    \
                                                                        \
  template<typename T> struct TNAME##_hasN<T, false>                    \
  { static bool const value = false; };                                 \
                                                                        \
  template<typename T, bool HasIt = TNAME##_hasN<T>::value>             \
  struct TNAME {                                                        \
    struct Fallback { detail::Marker N(...) const volatile; };          \
    struct Derived : T, Fallback {                                      \
      using T::N; using Fallback::N;                                    \
    };                                                                  \
                                                                        \
    static bool const value =                                           \
      sizeof (detail::Detector(),                                       \
              (*(Derived*)0) ARGS, *(char(*)[2])0)                      \
      == 2;                                                             \
  };                                                                    \
                                                                        \
  template<typename T> struct TNAME<T, false>                           \
  { static bool const value = false; }

IS_CALLABLE(f, .f(""), CanCallF); // callable with .f("")
IS_CALLABLE(f, .f(true), CanCallFb); // callable with .f(true)
IS_CALLABLE(g, .g(""), CanCallG); // callable with .g("")
IS_CALLABLE(c_str, .c_str(), CanCallCStr); // callable with .c_str()
IS_CALLABLE(operator(), (true), CanCallB); // callable with (true)

struct A { 
    void f(std::string); 
}; 

struct B : A {  }; 

int main() { 
  std::cout << CanCallF<B>::value << std::endl
            << CanCallFb<B>::value << std::endl
            << CanCallG<B>::value << std::endl
            << CanCallCStr<const std::string>::value << std::endl
            << CanCallB< boost::function<void(bool)> >::value << std::endl 
            << CanCallB< boost::function<void(bool*)> >::value << std::endl;
}


Output:
1
2
3
4
5
6
true
false
false
true
true
false


Create a new paste based on this one


Comments: