【问题标题】:Will concepts lite change the need of CRTP to achieve static polymorphism?精简版概念会改变 CRTP 实现静态多态性的需求吗?
【发布时间】:2013-11-10 03:44:49
【问题描述】:

自从我几年前发现CRTP 以来,我在很多地方都使用它来实现非常密集的面向计算的代码的编译时多态性。当人们关心通用性和运行时的最大性能时,以通用的方式将成员函数“注入”到类中是很棒的。

我已经阅读/观看了concepts lite 上的几件事,这将是(我希望)成为下一个C++ 标准的一部分。以更抽象和通用的方式设计函数绝对很棒,避免了我目前使用的 SFINAE/std::enable_if 的糟糕行。

我还没有测试过实现概念的g++ 分支,以便与它们一起玩,并以一种新的方式研究我喜欢的元编程方法。但也许你们中的一些人有。我的第一个想法是概念并不能解决静态多态的问题,但由于这类事情可能严重依赖技巧,我可能错了。所以我的问题如下:concepts lite 能否以更方便的方式实现编译时多态性(我们目前可以通过CRTP 实现)?(欢迎提供代码示例) .

【问题讨论】:

    标签: c++ metaprogramming crtp c++-concepts


    【解决方案1】:

    我不应该这么认为。 Concepts Lite 将取代您对enable_if 的使用,但我不确定它是否允许用于 CRTP 的新技术。另一方面,可能还有一些有趣的事情可以做。

    我会说我在较早的概念 lite 实现中遇到了一些 CRTP 问题。检查约束要求类型参数是完整类型。如果您在派生类上参数化了基类,则需要将检查推迟到使用点。例如:

    template<Fooable D>
    struct crtp {
      void f() {
        static_cast<D*>(this)->g();
      }
    };
    
    struct derived : crtp<derived> { // Error!
    };
    

    当您尝试检查Fooable&lt;derived&gt; 时,派生尚未定义。最好这样写:

    template<typename D>
    struct crtp {
      void f() requires Fooable<D>() {
        static_cast<D*>(this)->g();
      }
    };
    

    现在,Fooable&lt;D&gt;() 仅在调用 f() 时检查。

    仅供参考。

    【讨论】:

      【解决方案2】:

      所以我的问题如下:concepts lite 能否以更方便的方式实现编译时多态性(我们目前可以通过 CRTP 实现)? (欢迎提供代码示例)。

      不-他们一般不会压制CRTP。精简版概念主要是关于易于重载和定义泛型函数,以及易于语法检查:

      template<typename T>
      concept bool EqualityComparable()
      {
          return requires(T a, T b)
          {
              bool = {a == b};
              bool = {a != b};
          };
      }
      
      template<InputIterator I, EqualityComparable T>
      I find(I first, I last, T x);
      // or
      template<InputIterator I>
      I find(I first, I last, EqualityComparable x);
      

      我认为概念精简版会抑制std::enable_if 的许多用例。

      CRTP 有不同的用例,其中一些确实与重载有关,例如:

      template<typename Derived>
      void do_something(const CRTP_Base<Derived> &x);
      

      但CRTP 不限于重载,它还有其他应用:例如std::enable_shared_from_this 的主要用例并不意味着任何重载:

      class Widget : std::enable_shared_from_this<Widget>
      {
          // ...
      };
      

      CRTP 的一些用例甚至涉及到虚函数——例如Cloneable 接口的自动实现:

      // Simple example, no covariance, etc
      struct Base
      {
          typedef unique_ptr<Base> Unique;
      
          virtual Unique clone() const = 0;
          virtual ~Base() = default;
      };
      
      template<typename Derived>
      struct ImplementCloneable: protected Base
      {
          Unique clone() const override
          {
              return Unique(new Derived(static_cast<const Derived&>(*this)));
          }
      protected:
          ~ImplementCloneable() = default;
      };
      
      struct Widget: ImplementCloneable<Widget>
      {
      };
      

      【讨论】:

        【解决方案3】:

        据我了解,应该可以使用 Concepts Lite 来定义一种“静态接口”,即 Concept 要求类中存在某些成员函数,并且可以使用某些签名进行调用。在某些情况下,这似乎对静态多态性很有用。

        但是,我认为这并不是 Concepts Lite 的真正预期用途。在会谈中,我看到的建议似乎是应该有相对较少的概念,它们应该是相当基础的(就像“前向迭代器”的概念一样),而不是用于定义临时静态接口。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多