需要以 OutputIterator 作为参数的成员函数的 C++ 概念

C++ Concept that requires a member function with an OutputIterator as parameter

我在玩弄概念,遇到了障碍。又或许只是我脑子有问题

我想创建一个 class 来缓冲 "bulk-readable" 数据源。这样的数据源应该有一个成员函数,它接受一个 OutputIterator 并有一个像这样的签名:

template<typename It>
size_t read(It firstItem, size_t max)

我的想法是定义一个类似于 BulkReadable 的概念:

template<typename Source>
concept bool BulkReadable = 
    requires(Source s, Iter out, size_t max) {
        {s.read(out, max)} -> size_t;
    };

我在指定 Iter 时遇到问题。我可以在模板参数列表中添加另一个类型名称,但是想要使用该概念的 Buffer class 需要指定该参数的类型。

我想使用这个概念的理想方式是:

template<BulkReadable Source>
class Buffer {
  public: 
    Source& input:
    Buffer(Source& input) : input(input){}
    ...     

这种方法是否可行?如果是,如果我不 want/can 指定类型,我如何要求模板化方法签名?

这是一个常见的问题,即提出错误的概念问题,您尝试像使用基础 class 界面一样使用它们。使用基础 classes,您要声明派生的 classes 要实现的确切、特定的功能。您希望用户准确地实现您所说的他们必须执行的功能。

通过概念,您可以从另一个方向处理问题:您要创建什么用法

在您的代码中的某个时刻,您有一些对象、一些迭代器和一个大小。您将获取该对象,通过将迭代器和大小传递给它来调用一个函数,并且您期望返回某种类型的响应。而这个过程是有一定意义的。

那么那个就是你的概念。这是一个基于至少两个参数的概念:对象的类型和迭代器类型。所以这就是你应该创造的。

如果你有这个BulkReadable约束,那么你必须有一些接口约束它。将要调用 read 的接口。要调用 read,该接口必须有一个迭代器。

以下是选项:

  1. 接口由用户(直接或间接)指定了一个迭代器类型。如果是这种情况,那么您只需在函数的 BulkReadable 约束中使用该类型。如果迭代器类型基于一组复杂的参数操作,那么您将不得不进行一些计算来计算迭代器类型。

  2. 迭代器是静态确定的。然后在约束中使用已知的迭代器类型。

重点在于,在您尝试调用 read 时,您 知道 迭代器类型是什么。因此,您可以使用该类型来约束事物。因此,您的概念实际上并不是 BulkReadable,而是 BulkReadableFrom.

简而言之,您不应该限制类型能够采用任何类型(或某些约束内的任何类型)。针对您要使用它们的实际类型检查约束,最好是在它们变得相关的时候。