#include <type_traits>
#include <iostream>
struct test1 {
void Invoke() {};
};
struct test2 {
template<typename> void Invoke() {};
};
enum class InvokableKind {
NOT_INVOKABLE,
INVOKABLE_FUNCTION,
INVOKABLE_FUNCTION_TEMPLATE
};
template<typename Functor, class Enable = void>
struct get_invokable_kind {
const static InvokableKind value = InvokableKind::NOT_INVOKABLE;
};
template<typename Functor>
struct get_invokable_kind<
Functor,
decltype(Functor().Invoke())
>
{
const static InvokableKind value = InvokableKind::INVOKABLE_FUNCTION;
};
template<typename Functor>
struct get_invokable_kind<
Functor,
decltype(Functor().Invoke<void>())
>
{
const static InvokableKind value = InvokableKind::INVOKABLE_FUNCTION_TEMPLATE;
};
int main() {
using namespace std;
cout << (get_invokable_kind<test1>::value == InvokableKind::INVOKABLE_FUNCTION) << endl;
cout << (get_invokable_kind<test2>::value == InvokableKind::INVOKABLE_FUNCTION_TEMPLATE) << endl;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+CgpzdHJ1Y3QgdGVzdDEgewogICAgdm9pZCBJbnZva2UoKSB7fTsKfTsKCnN0cnVjdCB0ZXN0MiB7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZT4gdm9pZCBJbnZva2UoKSB7fTsKfTsKCgplbnVtIGNsYXNzIEludm9rYWJsZUtpbmQgewogICAgTk9UX0lOVk9LQUJMRSwKICAgIElOVk9LQUJMRV9GVU5DVElPTiwKICAgIElOVk9LQUJMRV9GVU5DVElPTl9URU1QTEFURQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgRnVuY3RvciwgY2xhc3MgRW5hYmxlID0gdm9pZD4Kc3RydWN0IGdldF9pbnZva2FibGVfa2luZCB7CiAgICBjb25zdCBzdGF0aWMgSW52b2thYmxlS2luZCB2YWx1ZSA9IEludm9rYWJsZUtpbmQ6Ok5PVF9JTlZPS0FCTEU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yPgpzdHJ1Y3QgZ2V0X2ludm9rYWJsZV9raW5kPAogIEZ1bmN0b3IsCiAgZGVjbHR5cGUoRnVuY3RvcigpLkludm9rZSgpKQogID4KewogICAgY29uc3Qgc3RhdGljIEludm9rYWJsZUtpbmQgdmFsdWUgPSBJbnZva2FibGVLaW5kOjpJTlZPS0FCTEVfRlVOQ1RJT047Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBGdW5jdG9yPgpzdHJ1Y3QgZ2V0X2ludm9rYWJsZV9raW5kPAogIEZ1bmN0b3IsCiAgZGVjbHR5cGUoRnVuY3RvcigpLkludm9rZTx2b2lkPigpKQogID4KewogICAgY29uc3Qgc3RhdGljIEludm9rYWJsZUtpbmQgdmFsdWUgPSBJbnZva2FibGVLaW5kOjpJTlZPS0FCTEVfRlVOQ1RJT05fVEVNUExBVEU7Cn07CgoKaW50IG1haW4oKSB7CiAgICB1c2luZyBuYW1lc3BhY2Ugc3RkOwoKICAgIGNvdXQgPDwgKGdldF9pbnZva2FibGVfa2luZDx0ZXN0MT46OnZhbHVlID09IEludm9rYWJsZUtpbmQ6OklOVk9LQUJMRV9GVU5DVElPTikgPDwgZW5kbDsKICAgIGNvdXQgPDwgKGdldF9pbnZva2FibGVfa2luZDx0ZXN0Mj46OnZhbHVlID09IEludm9rYWJsZUtpbmQ6OklOVk9LQUJMRV9GVU5DVElPTl9URU1QTEFURSkgPDwgZW5kbDsKCn0K