Advertisement
zhangsongcui

Perfect Forwarding

Jan 9th, 2012
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.92 KB | None | 0 0
  1. #include <iostream>
  2. #include <typeinfo>
  3. #include <type_traits>
  4.  
  5. template <typename Fn, typename T>
  6. void dy_call(Fn call_back, T& t) {
  7.     const std::type_info& info = typeid(call_back);
  8.     if ( info == typeid(void (*)(T&)))
  9.         ((void (*)(T&))call_back)(t);
  10.     else if ( info == typeid(void (*)(const T&)) )
  11.         ((void (*)(const T&))call_back)(t);
  12.     else if ( info == typeid(void (*)(T)) )
  13.         ((void (*)(T))call_back)(t);
  14.     else
  15.         std::cout << "dy_call(Fn call_back, T& t): Failed to match" << std::endl;
  16. }
  17.  
  18. template <typename Fn, typename T>
  19. void dy_call(Fn call_back, const T& t) {
  20.     const std::type_info& info = typeid(call_back);
  21.     if ( info == typeid(void (*)(const T&)) )
  22.         ((void (*)(const T&))call_back)(t);
  23.     else if ( info == typeid(void (*)(T)) )
  24.         ((void (*)(T))call_back)(t);
  25.     else
  26.         std::cout << "dy_call(Fn call_back, T& t): Failed to match" << std::endl;
  27. }
  28.  
  29. template <typename Fn, typename T>
  30. void dy_call_Cpp11(Fn call_back, T&& t) {
  31.     const std::type_info& info = typeid(call_back);
  32.     if ( !std::is_const<T>::value && std::is_reference<T>::value && info == typeid(void (*)(T)))    // 尝试普通引用
  33.         return ((void (*)(T&))call_back)(t);
  34.     if ( info == typeid(void (*)(const typename std::remove_reference<T>::type&)) )                 // 尝试const引用
  35.         return ((void (*)(const typename std::remove_reference<T>::type&))call_back)(t);
  36.     if ( info == typeid(void (*)(typename std::remove_reference<T>::type)) )                        // 尝试传值
  37.         return ((void (*)(typename std::remove_reference<T>::type))call_back)(t);
  38.     std::cout << "dy_call(Fn call_back, T& t): Failed to match" << std::endl;                       // 调用失败
  39. }
  40.  
  41. /////////////////////////////////////////////////////////////////////////////////////
  42.  
  43. using namespace std;
  44.  
  45. void fn_int(int arg) { cout << "fn_int is called" << endl; }
  46. void fn_int_r(int& arg) { cout << "fn_int_r is called" << endl; }
  47. void fn_int_cr(const int& arg) { cout << "fn_int_cr is called" << endl; }
  48.  
  49. inline void fn(int&& a) { cout << a; }
  50.  
  51. int main() {
  52.     fn(12);
  53.  
  54.     int a = 10;
  55.     int& r = a;
  56.     const int& cr = a;
  57.     dy_call(fn_int, 10);
  58.     dy_call(fn_int, a);
  59.     dy_call(fn_int, r);
  60.     dy_call(fn_int, cr);
  61.     dy_call(fn_int_r, 10);
  62.     dy_call(fn_int_r, a);
  63.     dy_call(fn_int_r, r);
  64.     dy_call(fn_int_r, cr);
  65.     dy_call(fn_int_cr, 10);
  66.     dy_call(fn_int_cr, a);
  67.     dy_call(fn_int_cr, r);
  68.     dy_call(fn_int_cr, cr);
  69.     cout << endl << endl;
  70.     dy_call_Cpp11(fn_int, 10);
  71.     dy_call_Cpp11(fn_int, a);
  72.     dy_call_Cpp11(fn_int, r);
  73.     dy_call_Cpp11(fn_int, cr);
  74.     dy_call_Cpp11(fn_int_r, 10);
  75.     dy_call_Cpp11(fn_int_r, a);
  76.     dy_call_Cpp11(fn_int_r, r);
  77.     dy_call_Cpp11(fn_int_r, cr);
  78.     dy_call_Cpp11(fn_int_cr, 10);
  79.     dy_call_Cpp11(fn_int_cr, a);
  80.     dy_call_Cpp11(fn_int_cr, r);
  81.     dy_call_Cpp11(fn_int_cr, cr);
  82. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement