How to pass reference to a vector as variadic argument? - c++

class Hex
{
short type;
Hex(short typE)
{
type = typE;
}
}
vector< vector<Hex> > hexes;
void HexRings(sf::Vector2i pos, void operation(sf::Vector2i, va_list), ...)
{
va_list args;
va_start(args, operation);
//block of irrelevant changes of pos
operation(pos, args);
//another block of irrelevant changes of pos
va_end(args);
}
void MakeHexTypeX(sf::Vector2i pos, va_list args)
{
hexes[pos.x][pos.y].type = va_arg(args, int);
}
void AddHexes(sf::Vector2i pos, va_list args)
{
vector<sf::Vector2i> returnThat;
returnThat = va_arg(args, vector<sf::Vector2i>());// how to make this line actually give back a reference to the original vector (visited)
list.push_back(sf::Vector2i(pos.x, pos.y));
}
int main()
{
vector<sf::Vector2i> visited;
for(int y=0; y<10; ++y)
{
hexes.push_back(vector<Hex>());
for(int x=0; x<10; ++x) hexes[x].push_back(Hex(0));
}
HexRings(sf::Vector2i(5, 5), AddHexesOfTypeX, visited);
HexRings(sf::Vector2i(5, 5), MakeHexTypeX, 1);
}
I have a function (HexRings), that iterates in a specific pattern on a two-dimensional vector. I want to have an ability to pass to this function a pointer to another function (like MakeHexTypeX or AddHexes), that performs a certain action on every visited tile. Everything is fine, if this function is changing the map, but I don't know what to do, if this function has to report back. For example, if I want to get all hexes of type X, that HexRings has encountered, the vector would have to be passed as reference, which I don't even know how to write.
TL;DR: How to pass reference to a vector as variadic argument?

Instead of passing the operation function into HexRings, I would pass a reference to a functor. Functors can store state and thus hold the vector you wish. Here we go:
struct processor {
// you will be overriding this for every different operation you want to perform
virtual void operator()(sf::Vector2i, va_list) = 0;
};
struct make_hex_type_x
: public processor {
void operator()(sf::Vector2i pos, va_list args) override {
hexes[pos.x][pos.y].type = va_arg(args, int);
}
};
struct add_hexes
: public processor {
private:
// this is our state
vector<sf::Vector2i> returnThat;
public:
void operator()(sf::Vector2i pos, va_list args) override {
returnThat = va_arg(args, vector<sf::Vector2i>());
list.push_back(sf::Vector2i(pos.x, pos.y));
}
// get access to your return vector
vector<sf::Vector2i>& get() {
return returnThat;
}
};
//now change HexRings so that it accepts the functor instead of a function
void HexRings(sf::Vector2i pos, processor& pr, ...)
{
va_list args;
va_start(args, operation);
//block of irrelevant changes of pos
pr(pos, args);
//another block of irrelevant changes of pos
va_end(args);
}
// and finally call as follows
int main()
{
vector<sf::Vector2i> visited;
for(int y=0; y<10; ++y)
{
hexes.push_back(vector<Hex>());
for(int x=0; x<10; ++x) hexes[x].push_back(Hex(0));
}
make_hex_type_x p1;
add_hexes p2;
HexRings(sf::Vector2i(5, 5), p2, visited);
HexRings(sf::Vector2i(5, 5), p1, 1);
// now extract your vector
auto& vec = p2.get();
}

Related

How to find/remove an element of vector of struct with specific parameter?

I have a struct of slotAndId struct, which is declared like so
typedef struct {
int slot;
int id;
} slotAndId;
Then I have a vector which holds many objects of type slotAndId...
slotAndId object;
vector<slotAndId> ids;
for (int i = 0; i < 20; i++) {
object.slot = i;
object.id = i + 2000; //random id as example, this will be generated by something else in reality.
ids.push_back(object);
}
If I then wanted to find, for example, if there's a slotAndId object which has slot equal to 20 within the vector, how would I do that in C++98? How would I then be able to delete that specific slotAndId object from the vector?
This is what std::find_if is for.
bool HasSlot20(const slotAndId& item)
{
return item.slot == 20;
}
int main()
{
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
HasSlot20
);
}
We need the extra function because C++98 doesn't have lambdas, but we can make it more flexible by using a functor instead:
struct HasSlot
{
HasSlot(const int id) : m_id(id) {}
bool operator()(const slotAndId& item)
{
return item.slot == m_id;
}
private:
const int m_id;
};
int main()
{
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
HasSlot(20)
);
}
or:
int main()
{
HasSlot finder(20);
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
finder
);
}
Now this logic is re-usable with different parameters.
Alternatively just have a loop!
If your container is very large, you might consider a different (or additional) data structure that can do this in better than linear time.

Returning 2D array pointer from class

I've got a class called Engine which holds and returns a buffer like so:
template <int width, int height, int meshSize>
class Engine {
public:
byte buffers[2][width][height];
byte fBuffer = 0;
byte** getBuffer() {
return buffers[fBuffer];
};
}
and I want to loop through the values in my main, but I can't seem to get it working..
byte* buff;
// main
buff = engine->getBuffer();
for (int x = 0; x < 320; x++) {
for (int y = 0; y < 320; y++) {
if (buff[x][y] != NULL) {
Serial.println(buff[x][y]);
}
// lcd.drawPixel(x, y, RGB(buff[x][y], buff[x][y], buff[x][y]));
}
}
What combination of asterisk and/or parenthesis will work?
You should return a reference to your array, rather than a pointer. I also recommend providing a const overload of getBuffer for read-only operations.
template <int width, int height, int meshSize>
class Engine {
public:
using BufferType = byte[width][height];
BufferType const& getBuffer() const {
return buffers[fBuffer];
};
BufferType& getBuffer() {
return buffers[fBuffer];
};
private:
BufferType buffers[2];
byte fBuffer = 0;
};
You can use auto to deduce this type when calling getBuffer for brevity:
auto& buff = engine->getBuffer(); // reference to the buffer

C++ Use Function Preconditions Or Wrapper Classes with Invariants?

I find myself writing a lot of functions that begin with many preconditions, and then I have to figure out how to handle all the invalid inputs and write tests for them.
Note that the codebase I work in does not allow throwing exceptions, in case that becomes relevant in this question.
I am wondering if there is any C++ design pattern where instead of having preconditions, input arguments are passed via wrapper classes that guarantee invariants. For example suppose I want a function to return the max value in a vector of ints. Normally I would do something like this:
// Return value indicates failure.
int MaxValue(const std::vector<int>& vec, int* max_value) {
if (vec.empty()) {
return EXIT_FAILURE;
}
*max_value = vec[0];
for (int element : vec) {
if (element > *max_value) {
*max_value = element;
}
}
return EXIT_SUCCESS;
}
But I am wondering if there is a design pattern to do something like this:
template <class T>
class NonEmptyVectorWrapper {
public:
static std::unique_ptr<NonEmptyVectorWrapper>
Create(const std::vector<T>& non_empty_vector) {
if (non_empty_vector.empty()) {
return std::unique_ptr<NonEmptyVectorWrapper>(nullptr);
}
return std::unique_ptr<NonEmptyVectorWrapper>(
new NonEmptyVectorWrapper(non_empty_vector));
}
const std::vector<T>& vector() const {
return non_empty_vector_;
}
private:
// Could implement move constructor/factory for efficiency.
NonEmptyVectorWrapper(const std::vector<T>& non_empty_vector)
: non_empty_vector_(non_empty_vector) {}
const std::vector<T> non_empty_vector_;
};
int MaxValue(const NonEmptyVectorWrapper<int>& vec_wrapper) {
const std::vector<int>& non_empty_vec = vec_wrapper.vector();
int max_value = non_empty_vec[0];
for (int element : non_empty_vec) {
if (element > max_value) {
max_value = element;
}
}
return max_value;
}
The main pro here is that you avoid unnecessary error handling in the function. A more complicated example where this could be useful:
// Finds the value in maybe_empty_vec which is closest to integer n.
// Return value indicates failure.
int GetValueClosestToInt(
const std::vector<int>& maybe_empty_vec,
int n,
int* closest_val);
std::vector<int> vector = GetRandomNonEmptyVector();
for (int i = 0; i < 10000; i++) {
int closest_val;
int success = GetValueClosestToInt(vector, i, &closest_val);
if (success) {
std::cout << closest_val;
} else {
// This never happens but we should handle it.
}
}
which wastefully checks that the vector is non-empty each time and checks for failure, versus
// Returns the value in the wrapped vector closest to n.
int GetValueClosestToInt(
const NonEmptyVectorWrapper& non_empty_vector_wrapper,
int n);
std::unique_ptr<NonEmptyVectorWrapper> non_empty_vector_wrapper =
NonEmptyVectorWrapper::Create(GetRandomNonEmptyVector());
for (int i = 0; i < 10000; i++) {
std::cout << GetValueClosestToInt(*non_empty_vector_wrapper, i);
}
which can't fail and gets rid of the needless input checking.
Is this design pattern a good idea, is there a better way to do it, and is there a name for it?

How can I access a member of a class from a function via pointer?

I wish to
create an array of class/struct items (c1)
then create an array of pointer to the original array (*cp1), which can be sorted
then access members of the class from within a function.
However I'm getting stuck at the initial function call.
Here's my basic code:
struct Car
{
int speed;
};
Car c1[5];
Car *cp1[5];
int main() {
for (int i=0;i<5;i++) {
c1[i].speed = i;
cp1[i] = &c1[i];
}
garage(cp1, 5);
}
void garage(Car **ar, int n) {
int p = (*ar[n / 2])->speed;
}
First of all, your garage function is not known to the compiler at the place where you call it, since it is defined below main. To fix it, either place the function definition above main, or introduce it with a prototype.
Second, at the line int p = (*ar[n / 2])->speed;, *ar[n/2] is not a pointer, so you should use . instead of ->, as in int p = (*ar[n / 2]).speed;
Funcion garage must be declared before you can refer it.
void garage(Car **ar, int n);
int main()
{
//...
}
void garage(Car **ar, int n) {
//...
}
Function main in C++ shall have return type int
int main()
{
//...
}
And within the function the correct expression will look
void garage(Car **ar, int n) {
int p = (*ar )[n / 2]).speed;
}
Or
void garage(Car **ar, int n) {
int p = ar[n / 2]->speed;
}
Or
void garage(Car **ar, int n) {
int p = ( *ar[n / 2] ).speed;
}
struct Car
{
int speed;
};
Car c1[5];
Car *cp1[5];
void garage(Car **ar, int n); // forward declare garage
int main()
{
for (int i=0;i<5;i++) {
c1[i].speed = i;
cp1[i] = &c1[i];
}
garage(cp1, 5);
}
void garage(Car **ar, int n) {
int p = ar[n / 2]->speed; // -> dereferences the pointer, you don't need to
}

C++ Passing args to void function

How can I pass args to this function:
int myClass::myFunc(void * aArgs){
return 0;
}
I call it this way:
thrd_create(&t, myClass::myFunc, (void*)0);
I need to pass multiple arguments to the function, how can I achieve it?
There are plenty of ways. For example:
struct Arg_Struct
{
int m_nArg1;
float m_fArg2;
bool m_bArg3;
}
//...
Arg_Struct* pStruct = new Arg_Struct;
pStruct->m_nArg1 = 0;
thrd_create(&t, myClass::myFunc, (void*)pStruct);
//...
int myClass::myFunc(void * aArgs){
Arg_Struct* pArgs = (Arg_Struct*)aArgs;
int n = pArgs->m_nArg1;
//...
return 0;
}