zoukankan      html  css  js  c++  java
  • "cppinsights"让泛型编程变的有趣

      在学习C++泛型编程的时候,是不是非常想知道你实例化的模板函数或模板类在编译器推导下是什么样子?今天就给大家简单介绍一个在线编译器:C++ Insights (cppinsights.io),它能够满足你的需求。

    一、常用编译器的痛点

      如下一个代码示例:

     1 template <typename T>
     2 T Max(T lhs, T rhs) 
     3 {
     4     return (lhs > rhs) ? lhs : rhs;
     5 }
     6 
     7 double Max(double lhs, double rhs)
     8 {
     9     return (lhs > rhs) ? lhs : rhs;
    10 }
    11 
    12 int main()
    13 {
    14     Max(10.5f, 5.5f); // (1)
    15     Max(10.5, 5.5);   // (2)
    16     system("pause");
    17 }

      你用常用编译器编译的时候知道第一个Max最终调用的是模板函数还是函数,第二个Max呢?恐怕在编译期间是不能的,但是在运行的时候通过断点能够知道。下面是使用visual studio 2019进行测试。

      编译期间:

            

       运行期间:

       

       

       第一个Max编译器选择函数模板,第二个Max选择普通的函数。或许同学们会说,这不就行了吗?

    二、泛型编程,真的没有你想象的那么好学

      如下示例:

     1 template <typename T1, typename T2>
     2 typename std::conditional<(sizeof(Tsizeof(T2)), T1, T2>::type Max1(T1 lhs, T2 rhs)
     3 {
     4     return (lhs > rhs) ? lhs : rhs;
     5 }
     6 
     7 template <typename T1, typename T2>
     8 typename std::common_type<T1, T2>::type Max2(T1 lhs, T2 rhs) 
     9 {
    10     return (lhs > rhs) ? lhs : rhs;
    11 }
    12 
    13 template <typename T1, typename T2>
    14 auto Max3(T1 lhs, T2 rhs)
    15 {
    16     return (lhs > rhs) ? lhs : rhs;
    17 }
    18 
    19 int main() {
    20 
    21     Max1(10.5f, 5.5);
    22     Max2(10.5f, 5.5);
    23     Max3(10.5f, 5.5);
    24 
    25     return 0;
    26 }

      你能区分Max1,Max2和Max3的实例化模板函数样子吗?(这里不考虑那些对泛型编程很熟的大佬们)。如果模板函数或模板类越来越复杂呢?

    三、让泛型编程变有趣的方法

      在学习泛型编程的时候,我在思考有什么办法看到模板实例化后的代码,网上搜索了很多相关资料,都没能找到符合自己需求的方法。这次我终于找到了,它就是cppinsights。

      如下实例代码:

     1 template <typename T>
     2 class Base
     3 {
     4   public:
     5       void Interface()
     6     {
     7           auto obj = static_cast<T&>(*this);
     8           obj.DoSomething();
     9     }
    10 };
    11 
    12 class D : public Base<D>
    13 {
    14     public:
    15         void DoSomething()
    16         {
    17         }
    18 };
    19 
    20 int main()
    21 {
    22       D d;
    23       d.Interface();
    24     return 0;
    25 }

      上面是奇异递归模板模式,同学们知道它被实例化后的样子是什么样的吗?下面是使用在线编译器编译后的代码的样子:

     1 template <typename T>
     2 class Base
     3 {
     4   public:
     5       void Interface()
     6     {
     7           auto obj = static_cast<T&>(*this);
     8           obj.DoSomething();
     9     }
    10 };
    11 
    12 /* First instantiated from: insights.cpp:14 */
    13 #ifdef INSIGHTS_USE_TEMPLATE
    14 template<>
    15 class Base<D>
    16 {
    17   
    18   public: 
    19   inline void Interface()
    20   {
    21     D obj = D(static_cast<D &>(*this));
    22     obj.DoSomething();
    23   }
    24   
    25   // inline constexpr Base() noexcept = default;
    26   // inline constexpr Base(const Base<D> &) noexcept = default;
    27 };
    28 
    29 #endif
    30 
    31 
    32 class D : public Base<D>
    33 {
    34   
    35   public: 
    36   inline void DoSomething()
    37   {
    38   }
    39   
    40   // inline constexpr D() noexcept = default;
    41   // inline constexpr D(const D &) noexcept = default;
    42 };
    43 
    44 
    45 
    46 int main()
    47 {
    48   D d = D();
    49   static_cast<Base<D>&>(d).Interface();
    50   return 0;
    51 }

      只需要将上面的代码拷贝到C++ Insights (cppinsights.io)上面点击编译,马上可视化看到实例化的代码样子。它是一个开源的项目,GitHub上有其相关的介绍:andreasfertig/cppinsights: C++ Insights - See your source code with the eyes of a compiler (github.com)。它的目的正如它说介绍的那样:”用编译器的眼光看你的源代码“。感兴趣的同学可以不妨一试。

    参考:

    1.Function Templates - ModernesCpp.com

  • 相关阅读:
    JavaScript中的memorizing技术
    在IE6/7/8下识别html5标签
    JavaScript中的类式继承和原型式继承
    OpenSUSE环境配置
    CentOS环境配置(LNMP)
    CentOS上OpenCC中文简繁体转换
    jQuery点击按钮页面滚动条向下滚动
    javascript-数组常用方法
    Tomcat配置常见错误问题解决方法
    字符串
  • 原文地址:https://www.cnblogs.com/smartNeo/p/14868490.html
Copyright © 2011-2022 走看看