How to reinitialize array of struct? - c++

As we know in c++, we can reinitialize an array arr of size N with a value 0 as,
fill (arr, arr + N, 0);
But I need to reinitialize the array with a struct S,
struct S {
int b[2];
}
The actual code is,
#include <iostream>
using namespace std;
struct Dog
{
int count[2];
};
int main(){
...
Dog dogs[N];
...
while (T--)
{
...
for (int i = 0; i < M; ++i)
{
fill(dogs, dogs+N, {0});
...
}
...
}
}

For the case:
struct Dog { int count[2]; };
Dog dogs[N];
you can use:
std::fill(dogs, dogs+N, Dog{});
The third argument to fill must have the right type already, the compiler does not deduce the type from the iterator. So you cannot just use {} or {0}.
Consider using std::begin(dogs), std::end(dogs) instead of dogs, dog+N as that removes the possibility of using the wrong value for N.
I'm not sure why fill was designed this way, as it is certainly possible to write a function which does accept initializer list as well as normal values:
#include <algorithm>
template<typename It>
void mfill(It begin, It end, typename std::remove_reference<decltype(*begin)>::type const &v)
{
std::fill(begin, end, v);
}
struct Dog { int count[2]; };
int main()
{
Dog dogs[5];
mfill(dogs, dogs+5, {});
}

You can use fill_n as follows:
struct Dog
{
int count[2];
};
int main(){
Dog dogs[4] = {};
dogs[0].count[0] = 1;
std::fill_n(dogs, 0, Dog{});
}
Since Dog is a pod structure, you can default construct it in the last parameter of fill_n

Related

A more simpler way to construct a list of arguments?

I'm trying to create map[per] sort of code, but i'm looking for a more simpler way of coding a constructor.
An example:
#define B {0, 0, 0, 0, 1}
struct A {
A(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0) {
this->args[0] = a;
this->args[1] = b;
this->args[2] = c;
this->args[3] = d;
this->args[4] = e;
};
~A() {};
int args[5];
};
By more simpler I mean something like:
#define C { {},{},{},{} }
struct B {
B(){};
int d,e;
char f,g;
}
struct A {
A(B b[] = {}) { };
B strct[4];
}
A a = C;
Which I just can't get to work.
If I'm understanding correctly, You're trying to find an easier way to construct class A:
struct A
{
A(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0)
: args{a, b, c, d, e} {};
~A(){};
int args[5];
};
We can use braces to initialize array int[5].
You could use a variadic template like...
struct A {
template <typename... T>
A(T... a) : args{a...} {};
int args[5];
};
int main() {
A a1(1); // Initializes only the first element individually; others get default initialized (zero-initialized)
A a2(1,2); // first two elements get initialized individually
// A a6(1,2,3,4,5,6); // Error: Excess elements in array initializer
}
One option (C++11 and later) use an initializer_list. For example;
#include <initializer_list>
#include <algorithm>
struct A
{
A(std::initializer_list<int> values) : args {0}
{
if (values.size() < 5)
std::copy(values.begin(), values.end(), args);
}
int args[5];
};
int main()
{
A a{1,2,3}; // note the values are in curly braces
for (int v : a.args) std::cout << v << ' ';
std::cout << '\n';
}
The args{0} in the initialiser list of the constructor initialises all elements of args to zero, and the loop accepts up to five values in the initiliser list. If there are more than five values supplied, all are ignored in the above.
If you want to use the arguments to create a container with an arbitrary number of int, you can do also use a standard container, such as vector.
#include <initializer_list>
#include <vector>
struct A
{
A(std::initializer_list<int> values) : args(values)
{
}
std::vector<int> args;
};
// same main() as above.
In this case, the number of elements in a.args (i.e. a.args.size()) will be the same as that supplied (no trailing zeros, unless explicitly supplied).

Initialize an array of template structures

The following snippet of code simply creates a structure that has three members. One of them is a callback function. I would like to initialize an array of these structures but I don't know the syntax, where I can have multiple callbacks with varying prototypes.
#include <iostream>
#include <functional>
template <typename Func>
struct Foo
{
Foo(int a, int b, Func func):
_a{a},
_b{b},
_func{func}{}
int _a;
int _b;
Func _func;
};
int main() {
auto test = [](){std::cout << "hello\n";};
Foo<std::function<void(void)>> foo(5,10, test);
foo._func();
//array version
//......................
}
How about this
//array version
Foo<std::function<void(void)>> a[] = { {5, 10, test}, {1, 2, test} };
Depending on what "array" you want to use, I think the creation is straight-forward, here with std::vector. You can use any container you like. Accessing here done with [], but could also be done with the at() method
typedef Foo<std::function<void(void)>> FooTypeDef;
int main() {
auto test = [](){std::cout << "hello\n";};
FooTypeDef foo(5,10, test);
foo._func();
//array version
//......................
std::vector<FooTypeDef> array;
array.push_back(foo);
array.push_back(foo);
array[0]._func();
array[1]._func();
}
And maybe use a typedef ;)

Vector of templated objects

I am working on a project that uses templated objects as a vector argument. I must strictly use objects and any primitive types. I'm working on a smaller example to help me grasp the bigger picture.
So far, here is what I have:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Thing {
public:
Thing(T type) {
memVar = type;
}
T getMemVar() {
return memVar;
}
private:
T memVar;
};
class U {
public:
U(int i) {
j = i;
}
int getJ () {
return j;
}
private:
int j;
};
int main() {
// your code goes here
vector < Thing <U> > v;
v.push_back(); // idk how to add new elements to this vector.
// I've tried: v.push_back(Thing <U> i(U)),
// v.push_back(U obj(4)), etc etc...
return 0;
}
I don't know how to add elements to this vector.
By example
v.push_back(Thing<U>(4));
If you can compile C++11 or newer, even simpler
v.emplace_back(4)
But, in both cases, you have to modify the constructor of Thing as follows
Thing(T type) : memVar(type) {
}
or add a default constructor in U
U () {
}
because your Thing constructor try to initialize memVar without arguments and next to copy type in memVar

How to create a Function that return any array of structs

I know there has to be a better and easier way to do what I am trying to do so I'm sorry for my lack of knowledge of programming. My program crashes when I call the function printStructValue. I have left comments to explain my thought process.
#include <iostream>
#include <vector>
using namespace std;
struct selection //vector array to tell me what is selected. ex:'w',5 is wall 5
{
char c;
int id;
}; vector<selection> Sel(20,selection());
struct walls //struct to hold wall data
{
int id;
int x,y,z;
int spriteState;
}; walls W[10];
struct floors //struct to hold floor data
{
int id;
int x,y,z;
}; floors F[10];
template <typename T,typename U>
T returnAnyArray(int st, T t,U u) //function that returns any type passed
{
if(st==1){t;} //if st==1, then return the first, walls W
if(st==2){u;} //if st==2, then return the second, floors F
}
template <typename T>
void printStructValue(T t, int d) //print any struct value
{
cout<<"passed:"<<t[d].x<<endl;
}
int main()
{
W[7].x=204; //init value
F[7].x= 73; //init value
//what I would like to happen is...
printStructValue( (returnAnyArray(1,W,F)),7); //W is returned and passed so W[7].x gets printed.
printStructValue( (returnAnyArray(2,W,F)),7); //F is returned and passed so F[7].x gets printed.
system("pause");
}
Your returnAnyArray function has to return something, but the types also have to match. Try this
template<typename T, typename U>
auto returnAnyArray(int st, T t, U u) -> decltype(st == 1 ? t : u)
{
return st == 1 ? t : u;
}
Your template function, returnAnyArray, doesn't actually return anything. Hence, printStructValue is being passed a garbage pointer. I'm surprised the compiler didn't catch this and print a warning or error. Perhaps because it's a template.
Do it the C++ way:
struct structuralMember {
virtual ~structualMember() { }
virtual void printme(std::ostream& out) = 0;
};
struct walls : public structualMember {
int x;
void printme(std::ostream& out) { out << x; }
};
struct floors : public structuralMember {
int x;
void printme(std::ostream& out) { out << x; }
};
Of course, that's not terribly sophisticated either, but it's a start.
Something working, but probably not what you are expecting ?
#include <iostream>
#include <vector>
using namespace std;
struct walls //struct to hold wall data
{
int id;
int x,y,z;
int spriteState;
};
walls W[10];
struct floors //struct to hold floor data
{
int id;
int x,y,z;
};
floors F[10];
void printStructValue(walls * t, int d) //print any struct value
{
cout<<"passed:" << t[d].x<<endl;
}
void printStructValue(floors * t, int d) //print any struct value
{
cout<<"passed:"<< t[d].x<<endl;
}
int main()
{
W[7].x=204; //init value
F[7].x= 73; //init value
//what I would like to happen is...
printStructValue( W,7); //W is returned and passed so W[7].x gets printed.
printStructValue( F,7); //F is returned and passed so F[7].x gets printed.
}

C++ : Array of struct as function parameter

I have a struct:
typedef struct
{
int nNum;
string str;
}KeyPair;
Let's say I initialize my struct:
KeyPair keys[] =
{ {0, "tester"},
{2, "yadah"},
{0, "tester"}
};
I want to use the initialized values in a function. How do I pass this array struct as a function parameter?
I have:
FetchKeys( KeyPair *pKeys)
{
//get the contents of keys[] here...
}
How about?
template<int N> void FetchKeys(KeyPair const (&r)[N]){}
EDIT 2:
Or even
template<int N> void FetchKeys(KeyPair const (*p)[N])
with the call as
FetchKeys(&keys);
You can do it as #MSalters mentioned, or you can create a std::vector<KeyPair> and pass it to the function. Here is a sample code:
using namespace std;
struct KeyPair
{
int nNum;
string str;
};
void fetchKeys(const vector<KeyPair>& keys)
{
//Go through elements of the vector
vector<KeyPair>::const_iterator iter = keys.begin();
for(; iter != keys.end(); ++iter)
{
const KeyPair& pair = *iter;
}
}
int main()
{
KeyPair keys[] = {{0, "tester"},
{2, "yadah"},
{0, "tester"}
};
//Create a vector out of the array you are having
vector<KeyPair> v(keys, keys + sizeof(keys)/sizeof(keys[0]));
//Pass this vector to the function. This is safe as vector knows
//how many element it contains
fetchKeys(v);
return 0;
}
Should be
// Definition
void FetchKeys( KeyPair *pKeys, int nKeys)
{
//get the contents of keys[] here...
}
// Call
FetchKeys(keys, sizeof(keys)/sizeof(keys[0]));
In c/c++ the name of the array (of any type) represents the address of the first element of the array, so
keys and &keys [0] are same.
You can pass any one of them for KeyPair*.
You just callFetchKeys(keys);
EDIT
Pay attention to declare FetchKeys' return type.
EDIT 2
If you also need the number of items, you add size as FetchKeys input parameters:
void FetchKeys(KeyPair*, size_t size);
and call FetchKeys(keys, sizeof(keys)/sizeof(*keys));
BTW, state all your question by editing your first post if you can.
Depending on what you want to do you can even use boost range and pass it to function as a pair of iterators:
void FetchKeys(KeyPair *begin, KeyPair *end)
FetchKeys(boost::begin(keys), boost::end(keys));
See this answer: How can I pass an array by reference to a function in C++?
Wrap it in a structure, nice and easy..
#include <iostream>
struct foo
{
int a;
int b;
};
template <typename _T, size_t _size>
struct array_of
{
static size_t size() { return _size; }
_T data[_size];
};
template <typename _at>
void test(_at & array)
{
cout << "size: " << _at::size() << std::endl;
}
int main(void)
{
array_of<foo, 3> a = {{ {1,2}, {2,2}, {3,2} }};
test(a);
}
EDIT: URGH, I can't see the toolbar to format the code correctly, hopefully the tags works..
i use VS 2008, and this works fine for me.
#include "stdafx.h"
typedef struct
{
int nNum;
CString str;
}KeyPair;
void FetchKeys( KeyPair *pKeys);
int _tmain(int argc, _TCHAR* argv[])
{
KeyPair keys[] =
{ {0, _T("tester")},
{2, _T("yadah")},
{0, _T("tester")}
};
FetchKeys(keys); //--> just pass the initialized variable.
return 0;
}
void FetchKeys(KeyPair *pKeys)
{
printf("%d, %s\n",pKeys[0].nNum, pKeys[0].str);
}
I don't understand the difficulty. correct me if i'm wrong. To keep it simple, i avoided using vectors, templates and etc.
edit: to know size of struct, you can pass one more arg.