static_cast<C*>(nullptr)->Subscribe(0)
O_o
Bad idea; a compiler is allowed to complain about the cast because it implies chasing a null, and as expected, some will complain.
Still, the bug in the original code still exists, so the bug hunt goes on...
You should doctor the type. The more specific flavor the less likely the compiler will travel the wrong direction.
Soma
Code:
#include <iostream>
template<typename T>
struct Has_Subscribe
{
typedef char yes[1];
typedef char no[2];
template<typename C, C> struct checker;
template<typename C> static yes& test(checker<void (C::*)(int), &C::Subscribe> *);
template<typename C> static no& test(...);
const static bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template<typename Parent_t>
struct base
{
template<typename NewParentT>
void bla() { std::cout << Has_Subscribe<Parent_t>::value << '\n'; }
};
struct foo: public base<foo>
{
void Subscribe(int) {}
};
struct foo2: public base<foo2> {};
int main()
{
foo _foo;
foo2 _foo2;
_foo.bla<foo>();
_foo2.bla<foo2>();
std::cout << "\n";
}
Code:
/* C++11 */
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>
#include <fstream>
#include <vector>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <functional>
template<typename T>
struct Has_Subscribe
{
typedef char yes[1];
typedef char no[2];
template<typename C, C> struct checker;
template<typename C> static yes& test(checker<decltype(C::Subscribe), &C::Subscribe> *);
template<typename C> static no& test(...);
const static bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};
template<typename Parent_t>
struct base
{
base()
{
test<Parent_t>();
}
template<typename T>
auto test() -> typename std::enable_if<Has_Subscribe<T>::value>::type { std::cout << "yes!\n"; }
template<typename T>
auto test() -> typename std::enable_if<!Has_Subscribe<T>::value>::type { std::cout << "no!\n"; }
};
struct foo: public base<foo>
{
void Subscribe(int) {}
};
struct foo2: public base<foo2> {};
int main()
{
foo _foo;
foo2 _foo2;
std::cout << "\n";
}