Should I replace (void *, size) with a GSL range?

Let's pretend that

int foo(void* p, size_t size_in_bytes); 

and suppose it makes no sense to type foo . I want to be a good coder and apply the basic principles of C ++. In particular, I want to use intervals instead of pairs (*, len). Well, span<void> will not compile (cannot add to void * ); and span<char> or span<uint8_t> etc. would imply that foo actually expects characters, which it cannot.

So should I use span<something-with-size-1> in this case or stick with void* ?

+5
source share
3 answers

What I chose, and what I think will be, in our opinion, a sound design is to implement a class called memory_region that has all the functionality like gsl::span (therefore, for example, it does not have begin () or end ()). This is not the same as a range of bytes, IMO - and I can never constructively mix them.

Here is my implementation (it is part of the repository of the kernel kernels associated with the DBMS, and the testing framework that I am working on, therefore, the CUDA related fragment, and this depends on some GSLs, in my case gsl-lite from MSs should also be OK).

0
source

There can be no general answer to this question.

For a function, to say that it accepts span<T> means that it takes a continuous array of values ​​without any form of transfer of ownership. If this description does not give a reasonable idea of ​​what is happening, then it should not accept span<T> .

For instance:

What should I do if the function checks to see if the buffer crosses an area in my memory space that, say, is mapped to a file?

This is not like span<T> . It looks like you should have a simple aggregate with a name that allows you to understand what this means:

 struct memory_region { void* p; size_t size_in_bytes; }; 

You can even give it a member function to test intersections. If you are creating a system to work with such areas of memory, I would recommend a more encapsulated class type with constructors, etc.

What type of function should consider what the data means. Preferably this meaning will be in a general sense, but at least he should say what it means for the function in question.


One more thing:

or span<uint8_t> etc. would imply that foo really expects characters

No, it will not. Although uint8_t almost certainly be the same size as an unsigned char , this does not mean that one would expect to pass an array of characters to any function that accepts span<uint8_t> . If this function wanted to advertise that it accepted characters, it would use an unsigned char .


I wanted to say that span<whatever> would mean a function to expect whatever .

Yes, the span requirement is that the actual array T given size is passed to it.

+5
source

The suggestion to the C ++ Standardization Committee is that if you want to pass a pointer to a sequence of bytes (which often happens that people want to do when passing void* ), you should pass a span<std::byte> , which relies on to the new type std::byte . However, this requires a small change in the locale.

In today's C ++, you can pass span<unsigned char> (typedef'd, as you find most descriptive) and get the same effect: access to a sequence of bytes.

0
source

All Articles