C ++概念要求使用带有OutputIterator作为参数的成员函数 [英] C++ Concept that requires a member function with an OutputIterator as parameter

查看:139
本文介绍了C ++概念要求使用带有OutputIterator作为参数的成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在玩概念游戏,遇到障碍。



我想创建一个缓冲大量可读数据源的类。这样的数据源应具有一个接受OutputIterator并具有如下签名的成员函数:

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

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

  template< typename来源> 
概念bool BulkReadable =
require(Source s,Iter out,size_t max){
{s.read(out,max)}-> size_t;
};

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



理想的方法我想如何使用该概念:

  template< BulkReadable Source> 
class Buffer {
public:
Source&输入:
Buffer(源和输入):输入(输入){}
...

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

解决方案

常见的问题是提出一个概念错误的问题,即您试图像使用基类接口一样在其中使用它们。对于基类,您要声明派生类要实现的确切的特定功能。您希望用户完全实现您要求的功能。



有了概念,您可以从另一个方向解决问题:用法



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



然后那个是您的概念。该概念至少基于两个参数:对象的类型和迭代器的类型。



如果您有此 BulkReadable 约束,那么您必须在其中限制一些接口它。该界面将调用 read 。要调用 read ,该接口必须具有迭代器。



因此,这里有以下选项:


  1. 用户为接口提供了迭代器类型(直接或间接)。如果是这种情况,则只需在函数的 BulkReadable 约束中使用该类型。如果迭代器类型基于一组复杂的参数操作,则必须进行一些计算才能计算出迭代器类型。


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


关键是,在您所需要的位置尝试调用 read ,您知道是什么迭代器类型。因此,您可以使用该类型约束事物。因此,您的概念并不是真正的 BulkReadable ,而是 BulkReadableFrom



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


I am playing with concepts and hit a roadblock. Or maybe it is just my mind that is blocked.

I want to create a class that buffers a "bulk-readable" data source. Such a datasource should have a member function that accepts an OutputIterator and has a signature like:

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

My idea was to define a BulkReadable concept similar to:

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

I am having trouble specifying Iter. I could add another typename to the template parameter list, but then the Buffer class that wants to use the concept would need to specify the type of that parameter.

The ideal way how I would like to use the concept is:

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

Is this approach even viable? If yes, how can I require a templated method signature if I do not want/can specify the type?

解决方案

This is a common problem of asking the wrong question of a concept, where you're trying to use them like you would a base class interface. With base classes, you're declaring the exact, specific functions that the derived classes are to implement. You want the user to implement exactly the function you say they must.

With concepts, you approach the issue from the other direction: what usage are you trying to create?

At some point in your code, you have some object, some iterator, and a size. And you're going to take that object, call a function by passing it the iterator and the size, and you expect a response back of a certain type. And this process has some meaning.

Then that is your concept. It's a concept that is based on at least 2 parameters: the type of the object and the iterator type. So that's what you should create.

If you have this BulkReadable constraint, then you must have some interface constrained on it. An interface that's going to call read. To call read, that interface must have an iterator.

So here are the options:

  1. The interface is given an iterator type (directly or indirectly) by the user. If that's the case, then you just use that type in the function's BulkReadable constraint. If the iterator type is based on a complex set of operations on parameters, then you'll have to do some computations to compute the iterator type.

  2. The iterator is statically determined. Then just use the known iterator type in the constraint.

The point being that, at the point where you're going to try to call read, you know what the iterator type is. And therefore, you can constrain things using that type. Your concept therefore is not really BulkReadable, but BulkReadableFrom.

In short, you shouldn't want to constrain a type on being able to take any type (or any type within some constraints). Check constraints against the actual types you're going to use them with, preferably at the point where they become relevant.

这篇关于C ++概念要求使用带有OutputIterator作为参数的成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆