Files
test/cpp/test_has_method.cpp

223 lines
3.8 KiB
C++

/* 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 <iostream>
#include <type_traits>
#include <utility>
#include <exception>
#include <sstream>
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 <class C>
struct has_touch
{
template <typename T, T t>
class helper{};
template <typename T>
static int test(T*, helper<void (T::*)(const char *), &T::touch>* = 0);
template <typename T>
static char test(...);
static const bool value = sizeof(test<C>(0))!=sizeof(char);
};
template <class S>
static
typename std::enable_if<has_touch<S>::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 <class S>
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 <typename T, T t>
class helper{};
template <class S>
static void touch( S * s, const char * p, helper<void (S::*)(const char*),&S::touch>* =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 <class S>
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;
}}