/* enum NothingType */
enum NothingType { Nothing };
/* type IsVoid<T> */
template <class T>
struct DoIsVoid
{
};
template <>
struct DoIsVoid<void>
{
using Ret = void ;
};
template <class T>
using IsVoid = typename DoIsVoid<T>::Ret ;
/* Action() */
template <class T>
void DoAction(T &,int,int)
{
Printf(Con,"default\n");
}
template <class T>
auto DoAction(T &obj,NothingType,int) -> IsVoid< decltype( obj.method2() ) >
{
Printf(Con,"method2\n");
obj.method2();
}
template <class T>
auto DoAction(T &obj,NothingType,NothingType) -> IsVoid< decltype( obj.method1() ) >
{
Printf(Con,"method1\n");
obj.method1();
}
template <class T>
void Action(T &obj)
{
DoAction(obj,Nothing,Nothing);
}
/* struct Test */
struct Test
{
};
/* struct Test1 */
struct Test1
{
void method1() {}
};
/* struct Test2 */
struct Test2
{
void method2() {}
};
/* struct Test12 */
struct Test12
{
void method1() {}
void method2() {}
};
/* main() */
int main()
{
Test test;
Test1 test1;
Test2 test2;
Test12 test12;
Action(test); // default
Action(test1); // method1
Action(test2); // method2
Action(test12); // method1
return 0;
}