4

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

我已经阅读/观看了几件事,concepts lite这将是(我希望)下一个C++标准的一部分。以更抽象和通用的方式设计功能绝对是美妙的,避免了SFINAE/std::enable_if我目前使用的那些糟糕的线条。

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

4

3 回答 3

6

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

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

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

struct derived : crtp<derived> { // Error!
};

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

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

现在,Fooable<D>()仅在f()调用时检查。

仅供参考。

于 2013-11-15T12:45:31.337 回答
5

所以我的问题如下:精简版概念能否以更方便的方式实现编译时多态性(正如我们目前可以通过 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不限于重载,它还有其他应用:例如主要用例 forstd::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>
{
};
于 2013-11-10T07:33:38.907 回答
0

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

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

于 2015-10-31T18:16:24.483 回答