0

I'm using a boost array as a buffer and wanted to pass it on as an argument to a function. The way I would like to pass it is so that the size is determined as another argument so that I can pass over buffers of varying sizes. Currently, my code is as follows:

void DataTransform(boost::array<char, 1024> data) {
    //do something
}

With a normal array I could have just used:

void DataTransform(char* data, uint_16 size) {
    //do something
}

How would I go about unwrapping the boost array to represent it as a pointer?

Sammi3
  • 367
  • 2
  • 5
  • 16

4 Answers4

4

If you have a plain array like char arr[SOME_SIZE]; then arr will decay to a pointer to its first element. That is, arr will decay to &arr[0].

Taking the address of an element of a boost::array (or, for that matter, std::array as well as std::vector) is valid as well and gives the same result.

So to get a pointer to the first element of the boost::array you simply do e.g. &data[0].


But if you don't want to deal with pointers, there's another way to handle your problem: Templates.

You can use a value template argument for the size of the boost::array, as in

template<size_t N>
void DataTransform(boost::array<char, N>& data) { ... }

and then you can pass a boost::array with char elements of any size to the function. The size will simply be deduced by the compiler:

boost::array<char, 512> data1;
boost::array<char, 1024> data2;
...
DataTransform(data1);
DataTransform(data2);
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
4

boost::array has a data() method that returns a pointer to the start of the array, and a size() method that returns the number of elements in the array:

DataTransform(some_array.data(), some_array.size())

Another option is to rework your DataTransform method to work on iterators:

template<typename T, typename U>
DataTransform(T begin, U end) {
    for(; begin != end; ++begin) {
        // do something with *begin
    }
}

And then you can call it like so:

DataTransform(std::begin(some_array), std::end(some_array))
DataTransform(some_c_array, some_c_array + some_c_array_size)
DataTransform(std::begin(some_list), std::end(some_list))
James Picone
  • 1,509
  • 9
  • 18
1

With a normal array I could have just used:

void DataTransform(char* data, uint_16 size) {
    //do something
}

You could do that also with a boost::array but it would be a step backwards. There are good reasons, why containers manage theirs size and you dont have to do the bookkeeping.

If you want this

void DataTransform(boost::array<char, 1024> data) {
    //do something
}

to accept boost::arrays of different size, I would suggest to parametrize the function on the size by making it a template:

#include <stdio.h>
#include <boost/array.hpp>

template <boost::array<char,1>::size_type size>
void DataTransform(boost::array<char, size> data) {
    //do something
}

int main(void)
{
    boost::array<char,10> x;
    boost::array<char,20> y;
    DataTransform(x);
    DataTransform(y);

}

PS: I am not that happy with boost::array<char,1>::size_type either and will open up a new question on that...

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

You can using c++ 20 std::span<T> which is a very lightweight abstraction of a contiguous sequence of values of type T somewhere in memory.

see What is a “span” and when should I use one? .

This container is intend to solve your problem and your function interface can be declare in a very clear way:

void DataTransform(std::span<char> data) {
    //do something
    for (std::size_t i = 0; i < data.size(); i++) {
       // ...
    }
}

You can just do this:

boost::array<char, 512>  d1;
boost::array<char, 1024> d2;
std::array<char, 512>    d3;
std::vector<char>        d4(512);
char                     d5[512];

DataTransform(d1);
DataTransform(d2);
DataTransform(d3);
DataTransform(d4);
DataTransform(d5); 
// Pass same buffer of varying size
DataTransform({d5, 256}); 

See online godbolt example.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90