概念lite会改变CRTP实现静态多态的需求吗?

Vin*_*ent 4 c++ metaprogramming crtp c++-concepts

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

我已经阅读/观看了几件事情concepts lite(我希望)是下一个C++标准的一部分.以更抽象和通用的方式设计函数是绝对美妙的,避免了SFINAE/std::enable_if我目前使用的可怕线条.

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

And*_*ton 6

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

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

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

struct derived : crtp<derived> { // Error!
};
Run Code Online (Sandbox Code Playgroud)

当您尝试检查时Fooable<derived>,派生尚未定义.最好这样写:

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

现在,Fooable<D>()仅在f()被调用时进行检查.

只是一个FYI.


Evg*_*yuk 5

所以我的问题如下:概念lite能否以更方便的方式实现编译时多态(我们目前可以通过CRTP实现)?(欢迎使用代码示例).

不 - 他们CRTP一般不会压制.Concepts lite主要是关于重载的简易性和定义泛型函数,以及语法检查的简易性:

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);
Run Code Online (Sandbox Code Playgroud)

我认为概念lite会压制很多用例std::enable_if.

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

template<typename Derived>
void do_something(const CRTP_Base<Derived> &x);
Run Code Online (Sandbox Code Playgroud)

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

class Widget : std::enable_shared_from_this<Widget>
{
    // ...
};
Run Code Online (Sandbox Code Playgroud)

一些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>
{
};
Run Code Online (Sandbox Code Playgroud)