function traits.

获取函数或成员函数的返回类型,参数类型,参数长度,类类型。

函数参数列表推断基于typelist:http://www.cnblogs.com/flytrace/p/3551414.html

先看一个普通函数非const的特化:

  1. template<typename R, typename... Args>
  2. struct function_traits<R (Args...)>
  3. {
  4. typedef R return_type;
  5. typedef typelist<Args...> arglist;
  6. enum { arg_count = sizeof...(Args) };
  7. template<unsigned int N>
  8. struct arg
  9. {
  10. typedef typename at<N, arglist>::type type;
  11. };
  12. };

使用:

  1. int testfunc1(char) { return 1; }
  2.  
  3. int main()
  4. {
  5. bool b;
  6. b = std::is_same< typename function_traits<int(double)>::return_type, int>::value;
  7. std::cout << "is same: " << b << std::endl;
  8.  
  9. b = std::is_same< typename function_traits<decltype(testfunc1)>::arg<0>::type, char>::value;
  10. std::cout << "is same: " << b << std::endl;
  11.  
  12. }

对于各种参数类型的普通函数,都能正确推断。但重载函数的情形需要我们考虑。如下我们增加testfunc1的重载版本:

  1. bool testfunc1(double, char) { return false; }

此时decltype(testfunc1)是无法编译通过的。这并不是我们的function_traits有问题。而是在没信息的情况下,decltype是无法选择testfunc1的重载版本的。除非我们在function_traits显式特化。

函数指针的function_traits也会遇到重载问题,如下是针对函数指针的function_traits:

  1. template<typename R, typename... Args>
  2. struct function_traits<R (*)(Args...)>
  3. {
  4. typedef R return_type;
  5. typedef typelist<Args...> arglist;
  6. enum { arg_count = sizeof...(Args) };
  7. template<unsigned int N>
  8. struct arg
  9. {
  10. typedef typename at<N, arglist>::type type;
  11. };
  12. };

decltye(&testfunc1)也是无法编译通过的。很显然,你自己作为编译器作者的话,若是没有额外的信息,让你使用decltype去推断一个可重载的函数类型,你怎么能够知道用户希望得到哪个类型?除了显示特化以提供给编译器信息外,对于函数指针,我们还可以提前转换,显式给以类型信息供编译器推断,如下:

  1. int (*castfunc)(char) = &testfunc1;
    b = std::is_same< typename function_traits<decltype(castfunc)>::arg<0>::type, char>::value;
  2. std::cout << "is same: " << b << std::endl;

castfunc1在定义时得到了testfunc1正确的重载类型,因此decltype在推断castfunc时就有了信息来选择正确的类型。

这并不是一个程序技术问题,更算是一个逻辑问题,就好像面对有多个定义的单词,没有上下文你是无法知道它要代表什么意思的。

这种显示转换并不会带给我们太多困扰。因为使用function_traits的场景,基本上是一种延迟推断手段。比如得到消息后,使用泛型手法分发消息处理。而消息处理函数我们在注册的时候肯定是知道函数类型的,在注册时我们就已经可以显示转换这个函数指针而不会遇到重载问题了。直接使用decltype(testfunc1)好像在我们测试function_traits时才会遇到,嗯,另一个人也遇到了,不然我不会试验。。。

然而确实存在一个可能,使我们可以传入testfunc1,而不用给予完整类型信息,虽然不适用于function_traits的情况。如下:

http://stackoverflow.com/questions/9054703/overloaded-function-as-argument-of-variadic-template-function

  1. template<typename ...Args>
  2. struct OverloadResolved
  3. {
  4. template<typename R>
  5. static auto static_doit( R (*f) (Args...), Args ... args ) -> R { return f(args...);}
  6. };
  7.  
  8. template<typename ...Args>
  9. auto deduce(Args...) -> OverloadResolved<Args...> { return OverloadResolved<Args...>(); }
  10.  
  11. template<typename T>
  12. struct dummy : public T { };
  13.  
  14. #define doit(f, ...) ( dummy<decltype(deduce( __VA_ARGS__ ))> :: static_doit(f, __VA_ARGS__) )

使用:

  1. char aa = 'a'; double ff = 0.1;
  2. std::cout << doit(testfunc1, aa) << " " << doit(testfunc1, ff, aa) << std::endl;

可以看到,虽然testfunc1有2个重载版本,但仍能正确的执行testfunc1(aa)和testfunc1(ff, aa).

当然因为此处给出了参数信息。这是一个运行时方案,而function_traits要求我们在编译期就推断。

以下添加类成员函数的function_traits:

  1. template <typename R, typename T, typename... Args>
  2. struct function_traits<R (T::*)(Args...)>
  3. {
  4. typedef T class_type;
  5. typedef R return_type;
  6. typedef typelist<Args...> arglist;
  7. enum { arg_count = sizeof...(Args) };
  8. template<unsigned int N>
  9. struct arg
  10. {
  11. typedef typename at<N, arglist>::type type;
  12. };
  13. };

还需要添加const,volatile修饰符的。以下是更完整的版本:

  1. template<typename T>
  2. struct function_traits;
  3.  
  4. template<typename R, typename... Args>
  5. struct function_traits<R (Args...)>
  6. {
  7. typedef R return_type;
  8. typedef typelist<Args...> arglist;
  9. enum { arg_count = sizeof...(Args) };
  10. template<unsigned int N>
  11. struct arg
  12. {
  13. typedef typename at<N, arglist>::type type;
  14. };
  15. };
  16.  
  17. template<typename R, typename... Args>
  18. struct function_traits<R (Args...) const>
  19. {
  20. typedef R return_type;
  21. typedef typelist<Args...> arglist;
  22. enum { arg_count = sizeof...(Args) };
  23. template<unsigned int N>
  24. struct arg
  25. {
  26. typedef typename at<N, arglist>::type type;
  27. };
  28. };
  29.  
  30. template<typename R, typename... Args>
  31. struct function_traits<R (Args...) volatile>
  32. {
  33. typedef R return_type;
  34. typedef typelist<Args...> arglist;
  35. enum { arg_count = sizeof...(Args) };
  36. template<unsigned int N>
  37. struct arg
  38. {
  39. typedef typename at<N, arglist>::type type;
  40. };
  41. };
  42.  
  43. template<typename R, typename... Args>
  44. struct function_traits<R (Args...) const volatile>
  45. {
  46. typedef R return_type;
  47. typedef typelist<Args...> arglist;
  48. enum { arg_count = sizeof...(Args) };
  49. template<unsigned int N>
  50. struct arg
  51. {
  52. typedef typename at<N, arglist>::type type;
  53. };
  54. };
  55.  
  56. template<typename R, typename... Args>
  57. struct function_traits<R (*)(Args...)>
  58. {
  59. typedef R return_type;
  60. typedef typelist<Args...> arglist;
  61. enum { arg_count = sizeof...(Args) };
  62. template<unsigned int N>
  63. struct arg
  64. {
  65. typedef typename at<N, arglist>::type type;
  66. };
  67. };
  68.  
  69. template <typename R, typename T, typename... Args>
  70. struct function_traits<R (T::*)(Args...)>
  71. {
  72. typedef T class_type;
  73. typedef R return_type;
  74. typedef typelist<Args...> arglist;
  75. enum { arg_count = sizeof...(Args) };
  76. template<unsigned int N>
  77. struct arg
  78. {
  79. typedef typename at<N, arglist>::type type;
  80. };
  81. };
  82.  
  83. template <typename R, typename T, typename... Args>
  84. struct function_traits<R (T::*)(Args...) const>
  85. {
  86. typedef T class_type;
  87. typedef R return_type;
  88. typedef typelist<Args...> arglist;
  89. enum { arg_count = sizeof...(Args) };
  90. template<unsigned int N>
  91. struct arg
  92. {
  93. typedef typename at<N, arglist>::type type;
  94. };
  95. };
  96.  
  97. template <typename R, typename T, typename... Args>
  98. struct function_traits<R (T::*)(Args...) volatile>
  99. {
  100. typedef T class_type;
  101. typedef R return_type;
  102. typedef typelist<Args...> arglist;
  103. enum { arg_count = sizeof...(Args) };
  104. template<unsigned int N>
  105. struct arg
  106. {
  107. typedef typename at<N, arglist>::type type;
  108. };
  109. };
  110.  
  111. template <typename R, typename T, typename... Args>
  112. struct function_traits<R (T::*)(Args...) const volatile>
  113. {
  114. typedef T class_type;
  115. typedef R return_type;
  116. typedef typelist<Args...> arglist;
  117. enum { arg_count = sizeof...(Args) };
  118. template<unsigned int N>
  119. struct arg
  120. {
  121. typedef typename at<N, arglist>::type type;
  122. };
  123. };

c++11 function_typetraits备忘的更多相关文章

  1. opencv-2.4.11编译备忘

    编译完成后,想测试example中例子,但是由于没有sudo权限,不能运行pkg-config查看opencv的--cflags和--libs. 记录一下,备忘: pkg-config --libs ...

  2. 11. 星际争霸之php设计模式--备忘模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  3. Nmap备忘单:从探索到漏洞利用(Part 2)

    这是我们的第二期NMAP备忘单(第一期在此).基本上,我们将讨论一些高级NMAP扫描的技术,我们将进行一个中间人攻击(MITM).现在,游戏开始了. TCP SYN扫描 SYN扫描是默认的且最流行的扫 ...

  4. [原]TCP/UDP使用细节备忘

    body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...

  5. HTML5终极备忘大全

    二.文字备忘之标签 HTML5中新增的标签 <article> 定义文章 <aside> 定义页面内容旁边的内容 <audio> 定义声音内容 <canvas ...

  6. [转] HTML5终极备忘大全(图片版+文字版)---张鑫旭

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1544 一.前言兼图片 ...

  7. Linq to XML 读取XML 备忘笔记

    本文转载:http://www.cnblogs.com/infozero/archive/2010/07/13/1776383.html Linq to XML 读取XML 备忘笔记 最近一个项目中有 ...

  8. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  9. 基于Prism.Windows的UWP开发备忘

    以前做UWP开发都是使用MvvmLight,主要是简单易上手,同时也写了很多MvvmLight的开发系列文章: UWP开发必备以及常用知识点总结 UWP开发之Mvvmlight实践九:基于MVVM的项 ...

随机推荐

  1. week7 ls

    week7 ls 实现ls: 实现ls -l:

  2. WebSocket ,Socket ,Http差异

    最近一直被Socket 被Http搞懵了,然后归类整理了下 首先需要知道网络七层,从上至下 应用,表示,回话,传输,网络,数据链路,物理,一共7层 WebSocket: 这个是在Html5提出的一种规 ...

  3. 『TensorFlow』读书笔记_ResNet_V2

    『PyTorch × TensorFlow』第十七弹_ResNet快速实现 要点 神经网络逐层加深有Degradiation问题,准确率先上升到饱和,再加深会下降,这不是过拟合,是测试集和训练集同时下 ...

  4. 【转】 SQL - 生成指定范围内的随机数

    DECLARE @Result INT DECLARE @Upper INT DECLARE @Lower INT SET @Lower = 1 SET @Upper = 10 SELECT @Res ...

  5. css3实现好看的边框效果

    1.html结构 <div class="box">box</div> <br> <div class="border1&quo ...

  6. centos 解决中文支持问题, 如此修改可以修正eclipse 乱码问题。

    一.中文支持 安装中文语言包: yum groupinstall chinese-support 修改字符编码配置,没有这个文件就创建它: vim /etc/sysconfig/i18n 为 LANG ...

  7. HashMap & Hashtable & CocurrentHashMap 与 ArrayList & CopyOnWriteArrayList

    1. 同步集合类如Hashtable和Vector虽能做到线程安全,但分别使用Collections.synchronizedMap()方法和Collections.synchronizedList( ...

  8. Python基础10_函数

    直接贴笔记 : #!/usr/bin/env python # coding:utf-8 # 定义函数时要写成良好的注释习惯 通常用三个单引号 def test(x): ''' 计算一个y=2*x+1 ...

  9. binary and out mode to open a file

    When I use binary and out mode to open a exist file, and to modify the 4th and 8th byte data to 0x78 ...

  10. python自学第9天,装饰器

    装饰器:本质是函数(装饰其它函数) 就是为其它函数添加附加功能 原则:1.不能修改被装饰函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数即变量 2.高阶函数:a.把一个 ...