/* Check cf5-opt.vim defs. VIM: let g:lcppflags="-std=c++11 -O2 -pthread" VIM: let g:wcppflags="/O2 /EHsc /DWIN32" VIM: let g:cppflags=g:Iboost.g:Itbb VIM: let g:ldflags=g:Lboost.g:Ltbb.g:tbbmalloc.g:tbbmproxy VIM: let g:ldlibpath=g:Bboost.g:Btbb VIM: let g:argv="" VIM-: let g:cf5output=0 */ #include #include #include #include #include struct A { void touch( const char * ) { std::cout << "A::touch"; } }; struct B { }; struct C : public A { }; struct D { void touch( int ) { std::cout << "D::touch"; } }; struct call_touch { template struct has_touch { template class helper{}; template static int test(T*, helper* = 0); template static char test(...); static const bool value = sizeof(test(0))!=sizeof(char); }; template static typename std::enable_if::value,void>::type touch( S * s, const char * p) { std::cout << "call_touch: calling -> "; return s->touch(p); } static void touch(...) { std::cout << "call_touch: no method to call"; } }; struct call_touch2 { template static void touch( S * s, const char * p, decltype(&S::touch)* =0) { std::cout << "call_touch2: calling -> "; return s->touch(p); } static void touch(...) { std::cout << "call_touch2: no method to call"; } }; struct call_touch3 { template class helper{}; template static void touch( S * s, const char * p, helper* =0) { std::cout << "call_touch3: calling -> "; return s->touch(p); } static void touch(...) { std::cout << "call_touch3: no method to call"; } }; struct call_touch4 { template static decltype( ((S*)0)->touch((const char *)(0)) ) touch( S * s, const char * p ) { std::cout << "call_touch4: calling -> "; return s->touch(p); } static void touch(...) { std::cout << "call_touch4: no method to call"; } }; int main ( void ) {try{ A a; B b; C c; D d; std::cout << std::endl; std::cout << "test a: "; call_touch::touch( &a, 0 ); std::cout << std::endl; std::cout << "test b: "; call_touch::touch( &b, 0 ); std::cout << std::endl; std::cout << "test c: "; call_touch::touch( &c, 0 ); std::cout << std::endl; std::cout << "test d: "; call_touch::touch( &d, 0 ); std::cout << std::endl; std::cout << std::endl; std::cout << "test a: "; call_touch2::touch( &a, 0 ); std::cout << std::endl; std::cout << "test b: "; call_touch2::touch( &b, 0 ); std::cout << std::endl; std::cout << "test c: "; call_touch2::touch( &c, 0 ); std::cout << std::endl; // Compiler error is generated. // // std::cout << "test d: "; // call_touch2::touch( &d, 0 ); // std::cout << std::endl; std::cout << std::endl; std::cout << "test a: "; call_touch3::touch( &a, 0 ); std::cout << std::endl; std::cout << "test b: "; call_touch3::touch( &b, 0 ); std::cout << std::endl; std::cout << "test c: "; call_touch3::touch( &c, 0 ); std::cout << std::endl; std::cout << "test d: "; call_touch3::touch( &d, 0 ); std::cout << std::endl; std::cout << std::endl; std::cout << "test a: "; call_touch4::touch( &a, 0 ); std::cout << std::endl; std::cout << "test b: "; call_touch4::touch( &b, 0 ); std::cout << std::endl; std::cout << "test c: "; call_touch4::touch( &c, 0 ); std::cout << std::endl; std::cout << "test d: "; call_touch4::touch( &d, 0 ); std::cout << std::endl; return 0; } catch ( const std::exception& e ) { std::cerr << std::endl << "std::exception(\"" << e.what() << "\")." << std::endl; return 2; } catch ( ... ) { std::cerr << std::endl << "unknown exception." << std::endl; return 1; }}