Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Suppose I have

int foo(void* p, size_t size_in_bytes);

and assume it doesn't make sense to make foo typed. I want to be a good coder and apply the C++ core guidelines. Specifically, I want to use spans instead of (*, len) pairs. Well, span<void> won't compile (can't add to a void *); and span<char> or span<uint8_t> etc. would imply foo actually expects chars, which it might not.

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

like image 745
einpoklum Avatar asked May 26 '16 21:05

einpoklum


2 Answers

There can be no general answer to this question.

For a function to say that it takes a span<T> means that it takes a contiguous array of values, without any form of ownership transference. If that description does not reasonably represent what is going on, then it should not take a span<T>.

For example:

What if the function checks whether the buffer intersects a region in my memory space which is, say, mapped to a file?

That doesn't sound like a span<T>. That sounds like you should have a simple aggregate with a name that makes it clear what it means:

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

You could even give it a member function for testing intersections. If you are making a system for dealing with such regions of memory, I might advise a more encapsulated class type with constructors and such.

What type the function takes should explain what the data means. Preferably this meaning would be in a general sense, but at the very least, it should say what it means for the function in question.


One more thing:

or span<uint8_t> etc. would imply foo actually expects chars

No, it would not. While uint8_t will almost certainly have the same size as an unsigned char, that does not mean that one would expect to be able to pass an array of characters to any function which takes span<uint8_t>. If that function wanted to advertise that it accepted characters, it would have used unsigned char.


I meant to say span<whatever> would imply the function expect whatever's.

Yes, the requirement for spans is that it is passed an actual array of Ts of the given size.

like image 65
Nicol Bolas Avatar answered Sep 29 '22 12:09

Nicol Bolas


The proposal before the C++ standardization committee is that if you want to pass around a pointer to a sequence of bytes (which is often what people want to do when passing void* around), then you would pass a span<std::byte>, which relies upon a new std::byte type. However, that requires a small change to the language standard to be legal.

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

like image 33
neilmacintosh Avatar answered Sep 29 '22 14:09

neilmacintosh