Passing a 2d array of vector to a class constructor - c++

In my code, I have some data stored in an 2d array of vector and I'd like to use it in another class to process the data but I can't find a way to do that.
Here is a sample of what I tried :
vector<IndividualData> vecArray[5][5]; // The one I want to pass to the class
MyClass::MyClass(vector<IndividualData> data[][5], ...):_data(data)
Is there a good way to do that?
I also tried with the std::array but I can't make it work :
array<array<vector<IndividualData>, 5>, 5> testVec; // Ther one I want to pass to the class
MyClass::MyClass(array<array<vector<IndividualData>, 5>, 5>& data, ...): _data(data)
When I want to use it in the class, I get the following error :
Type 'array<array<vector, 5>, 5>' does not provide a subscript operator
With
printf("%d\r\n", _data[0][0][0].param);
and
array<array<vector<IndividualData>, 5>, 5>& _data;
Thank's in advance for your replies

This works for me:
using My2DArrayOfVec = std::array<std::array<std::vector<IndividualData>, 5>, 5>;
class MyClass
{
My2DArrayOfVec _data;
public:
MyClass(My2DArrayOfVec const& data, ...) : _data(data) {}
void useIt() const { printf("%d\r\n", _data[0][0][0].param); }
};
By having an alias, I always use the same types, My2DArrayOfVec, inside and outside of my class even when I'm experimenting.

Related

How to use a template member function as an argument to another template member function?

So I'm experimenting with templates and probably I have a syntax problem somewhere. I'm trying to write a class, which takes a vector of selected items, converts their properties to boolean arrays, and then generates object which represent the state of the whole selection> This object is sent to the UI view and shown on a context menu with tri-state checkboxes. I know how to write this the long and hard way, but I want to avoid code duplication, so I decided to go with templates. The problem is that I can't pass a member function to another member function. I'm getting compile error C3867 non-standard syntax; use '&' to create a pointer to member.
First: Sorry, if it is a duplicate. Second: sorry for the long example, but I have no idea where my mistake is.
#include <array>
#include <vector>
#include "Item.h"
enum class CheckState {unchecked, checked, partially_checked}; //the state of the context menu checkboxes
struct CheckBoxModels //this is the final product we want to get
{
std::array<CheckState, 10> general;
std::array<CheckState, 6> surface;
std::array<CheckState, 7> other;
};
class CheckModelGenerator{ //this class has to generate the chechBoxModel by taking a vector of pointers to the selected Items;
std::array<bool, 10> getGeneralStatus(const Item& item); //each of these knows how to get a specific list of properties from an item
std::array<bool, 6> getSurfaceStatus(const Item& item); //and represent it with boolean
std::array<bool, 7> getSomeOtherStatus(const Item& item);//depending on whether they exist or not;
template<int Size> //using this to call ANY of the functions above
using getAnyStatus = std::array<bool, Size>(CheckModelGenerator::*) (const Item& item);
template<int size> //a member function that converts the bool arrays to CheckState arrays, by iterrating trough the selected items
std::array<CheckState, size> getCheckStateFromAnyStatus(const std::vector<Item*>& selectedItems, getAnyStatus<size> getStatus);
public:
CheckBoxModels getAllCheckBoxModels(std::vector<Item*>& selectedItems) // this here creates the final product;
{
CheckBoxModels models;
models.general = getCheckStateFromAnyStatus(selectedItems, getGeneralStatus); //I'm having problem actually calling those template functions!
models.surface = getCheckStateFromAnyStatus(selectedItems, getSurfaceStatus);
models.other = getCheckStateFromAnyStatus(selectedItems, getSomeOtherStatus);
return models;
}
};
Well, you really are missing & and the names have to be prepended with the class name. Try this:
models.general = getCheckStateFromAnyStatus(selectedItems, &CheckModelGenerator::getGeneralStatus);
models.surface = getCheckStateFromAnyStatus(selectedItems, &CheckModelGenerator::getSurfaceStatus);
models.other = getCheckStateFromAnyStatus(selectedItems, &CheckModelGenerator::getSomeOtherStatus);

How to slice map of structs into a sub-set with the same keys?

I have a map of structs that holds several named values like this:
struct MyData {
MyType dataA;
std::string dataB;
int dataC;
};
typedef std::pair<std::string, MyData> PairType;
std::map<PairType::first_type, PairType::second_type> dataMap;
This is defined in a header file of a compilation unit that calls a function from a library.
Because the library function does not know about my type definitions, I can't pass dataMap directly.
The function only actually needs the dataA struct member and already knows about MyType, so I could pass a std::map<std::string, MyType> instead.
Whats the most elegant way of cutting just the data I need from the map of structs and save it into a new map with the same keys but only the type and values from dataA?
Preferably for C++0x without usage of boost or other external libraries, but solutions for newer standards are also welcome for educational purposes.
I'm basically looking for an equivalent of Python's
newDict = {key:value.dataA for (key,value) in oldDict.items()}
You can use a ranged based for loop to really easily make a copy. That would look like
std::map<std::string, MyType> my_type_map;
for (const auto& pair : dataMap)
{
my_type_map.emplace(pair.first, pair.second.dataA);
}
If you want this as a single expression, you are going to need something like boost::transform_iterator, either by including that, or writing an iterator yourself.
Given a conversion function (or equivalent lambda)
std::pair<std::string, MyType> convert(PairType& pair){
return { pair.first, pair.second.dataA };
};
You can declare newDict and populate it
/* can be const */ std::map<std::string, MyType> newDict {
boost::make_transform_iterator(oldDict.begin(), convert),
boost::make_transform_iterator(oldDict.end(), convert)
};
Or you can use a view type
auto newDict = boost::copy_range<std::map<std::string, MyType>>(oldDict | std::ranges::views::transform(convert));

SFML accessing array inside std::vector

In class A I have:
class A{
A(){};
std::vector<sf::Vertex[2]> lines{ 5 };
};
And I somehow need to access sf::Vertex 0 and 1 of all the line objects in std::vector. The SFML documentation states on lines:
sf::Vertex line[] =
{
sf::Vertex(sf::Vector2f(10, 10)),
sf::Vertex(sf::Vector2f(150, 150))
};
I tried many things, but syntax just doesn't work out, from this:
std::vector lines{ {Vertex(100,100),Vertex( 300,300)},... };
to this:
A(){
lines[0]->sf::Vertex[0] = (100,100);
...};
But it just doesn't work out. What's the proper syntax?
An array is not a valid element type for a vector (or any other standard Container). It doesn't satisfy the requirement of being Erasable. You can instead use a class that has the array as a member. The standard library has a template for such array wrapper: std::vector<std::array<sf::Vertex, 2>>.

Is there a good way to combine or simplify these STL maps?

I'm writing a class that needs to store a bunch of different primitives and classes. I've decided to make a map for each different data type where the key in the map would be the name of the variable, and the value in the map would be the value of the variable. My maps are defined like this:
std::unordered_map<std::string, int> myInts;
std::unordered_map<std::string, float> myFloats;
std::unordered_map<std::string, Something> mySomethings;
For each map, I have to write two methods, one which will get the value of some variable and one which will set the value of some variable like so:
void setMyInt(const std::string &varName, int newVal) {
myInts[varName] = newVal;
}
int getMyInt(const std::string &varName) {
return myInts[varName];
}
This is all fine and easy, however, I ended up with 8 different maps, and 16 of these get set methods. This doesn't seem very efficient or clean to me, not to mention that every time I need to store a new data type I have to define a new map and write 2 new get-set methods.
I considered getting rid of the get set methods and instead writing 2 template methods which would take in the type of the variable which the user needs to get or set, and then accessing the proper set to perform the operation, like so:
template<class Type>
void getVariable<Type>(const std::string &varName) {
// if Type == int -> return myInts[varName];
// else if Type == float -> return myFloats[varName];
}
This seems like a really poor approach since the user could pass in types which are not supported by the class, and the method breaks C++'s rule of not being really generic.
Another idea I had was writing some Variable class which would have all of the fields that this class should store, along with some enum that defines what Variable the class is actually being used for, and then making a map of this Variable class like this:
enum Type {
TYPE_INT,
TYPE_FLOAT,
TYPE_SOMETHING
class Variable {
Type type;
int myInt;
float myFloat;
Something mySomething;
}
std::unordered_map<std::string, Variable> myVariables;
But this also seems like a really poor solution, or at least one which is difficult to understand. Is there some smart way to make this class store different types?
How about a template class like below:
template<typename ValueType>
class UnorderedStringMap : public std::unordered_map<std::string, ValueType> {
public:
...
void setValue(const std::string &varName, ValueType newVal) {
std::unordered_map::operator[](varName) = newVal;
}
const ValueType& getValue(const std::string &varName) {
return std::unordered_map::operator[](varName);
}
...
}
UnorderedStringMap<int> myInts;
UnorderedStringMap<float> myFloats;
You can then use it as a normal std::unordered_map as well.

How to fill and access to std::map<std::pair<enum1, enum2>, funcPtr>?

I would like to know how to fill this type of map and mainly the way to access to the function pointer.
The map :
enum enum1
{
val11,
val12,
val13
};
enum enum2
{
val21,
val22,
val23
};
typedef void(MyClass::*funcPtr)();
std::map<std::pair<enum1, enum2>, funcPtr> map;
I fill it like this, it seems to work:
map.insert(std::make_pair(std::make_pair(val11, val21), &MyClass::init));
But I can't access to the function like this:
map[std::make_pair<val11, val21>]();
What am I doing wrong?
You are using the wrong parentheses with make_pair and need to call the member function on some instance of MyClass (using the .* or ->* operators):
MyClass obj;
(obj.*map[std::make_pair(val11, val21)])();