Priority_queue functor use C++ - c++

I have stumbled upon some weird use of priority_queue, I would love to obtain some proper explanation of why on earth it's plausibile/valid to use something like this in priority_queue declaration:
typedef priority_queue<RandomContainer, **vector<RandomContainer>**, FunctorName> NewQueueName;
Let's say we've got some struct called SPerson:
struct SPerson
{
int age;
string name;
string surname;
};
and some functor which will be helpful to sort all elements of queue accordingly to our likeing:
struct TheWayILike
{
bool operator()(const SPerson &name1, const SPerson &name2)
{
if(name1.name > name2.name) return true;
if(name1.name < name2.name) return false;
return false;
}
};
Now we can declare our priority_queue which will be based upon elements from the struct and which will be ordered by functor called TheWayILike.
priority_queue<SPerson, TheWayILike>
or shorter way by using typedef and single name like so:
typedef priority_queue<SPerson, TheyWayILike> newNameForPQ;
but somehow it's wrong and I have to add following line: vector
Question:
Why on earth do I have to squize my personally customized data types into vector ?
Why it must be a vector and why should I use it anyway ?
Why do I need to fill my data into vector ? I haven't read about it in official priority_queue documentation, so I would love to obtain some easy to understand explanation for rookie programmer.
Cheers!

You dont' have to. But look at the declaration of the priority_queue class template:
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
You can't provide a custom comparator type argument unless you also provide the underlying container to hold the data in. The author of the line above decided vector was the best choice. Any other container that fits the requirements can also be used, e.g. deque, but vector proves to be best for most applications so it is the default.

Related

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));

What realization to choose for heterogenous container that uses std::variant for data storage?

For a program which is a simple rogue-like game, I need a container for storing contents of each room be it enemies, loot, traps, lore-entries etc. Since set of types being held in each room is finite and predetermined I've settled for std::variant for data storage. I also will need methods to process the data and here comes the problem. Now due to lack of experience I struggle to choose realization that won't become a burden in long term.
Objective style approach:
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
template <typename V>
class HVector
{
private:
class HVElem
{
private:
V data;
public:
V getData();
};
std::vector<HVElem> content;
public:
void push(V newData);
};
int main()
{
HVector<myVariant> hVector;
}
Functional approach:
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
template <typename V> void push(std::vector<V> hVector, V newData)
{
// something
}
int main()
{
std::vector hVector<myVariant>;
}
Questions:
Which of the two approaches is better? I have a strong feeling that simply using std::vector<std::variant<>> with some template functions is enough in this case. Is using objective style even requiered here?
How can I prevent the program from creating a container that holds anything other than std::variant<>? Is there a way to simply list types in type aliases so that I could simply write std::vector<std::variant<myTypes>>?
Which of the two approaches is better?
Neither, see option 3 below.
How can I prevent the program from creating a container that holds anything other than std::variant<>?
using myVariant = std::variant<TYpe1, Type2 ... TypeN>;
using myVector = std::vector<myVariant>;

Mapping data members of a class

I am trying to design a data stuctures, which would enhance/supplement an existing one by storing some additional data about it's members.
Let's say we have:
class A {
int x;
string y;
};
And we want to have a GUI component associated with it, so the data members have corresponding GUI elements. I'd like to map the members to their respective components. Something like
class GuiA {
int x;
string y;
map<MemberHandle, GuiElement*> guiHandles;
}
I don't have any restrictions, but I'd like the result to be easily convertible to the original type.
I am aware, that I could introduce a template e.g. GuiElementMember holding original data plus the GuiElement pointer, and swap class member for their decorated counterparts, so it would look like:
class GuiA {
GuiElementMember<int> x;
GuiElementMember<string> y;
}
but I'd like to avoid it, as it completely changes access patterns to data members and bloats it. I.e. it results with data members interleaved with pointers, that are not easy to strip out.
Ideally it would be possible to write GuiA as a derived class of A, or as a composition of A and something additional.
I was thinking about something like a template that class could produce the map. I could yield to write a custom class per component, but I don't think there is an easy way to map data members, so on the clients side it would look like getGuiMember(GuiA::x). The pointer to data member contains the member original type. I don't think it is possible to have something like "type-erased pointer to member" that could serve as a MemberHandle type.
The only thing that comes to my mind is a custom enum per component which would enumerate data members and serve as key type for a map (or a vector in this case), but it seems as an awful lot of information duplication and maintenance.
Is there some technique that allows mapping data members?
I don't really care about the implementational complexity as long as the interface is easy. I welcome boost or template magic. I also don't care about the performance of additional data access, it's extra stuff, but the plain class usage should not be impacted, so introduction of indirection that cannot be optimized is less welcomed.
EDIT: Please don't hinge on GUI thing it's an example. I am only concerned about storing some additional data per member without composing it with the member.
You can use BOOST_FUSION_DEFINE_STRUCT to define your structures that can be iterated over with a for_each loop:
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <unordered_map>
#include <string>
#include <cstdint>
BOOST_FUSION_DEFINE_STRUCT(
(demo), employee,
(std::string, name)
(int, age)
)
struct GuiElement;
GuiElement* createGuiElement(char const* name);
using Mapping = std::unordered_map<size_t, GuiElement*>;
template<class T>
Mapping create_mapping(T&& t) {
Mapping mapping;
boost::fusion::for_each(t, [&](auto& member) {
auto offset = reinterpret_cast<uintptr_t>(&member) - reinterpret_cast<uintptr_t>(&t);
mapping[offset];
});
return mapping;
}
template<class T, class M>
GuiElement*& get_mapping_element(Mapping& mapping, T const& t, M const& member) {
auto offset = reinterpret_cast<uintptr_t>(&member) - reinterpret_cast<uintptr_t>(&t);
auto found = mapping.find(offset);
if(found == mapping.end())
std::abort();
return found->second;
}
int main() {
auto employee_mapping = create_mapping(demo::employee{});
demo::employee e1;
get_mapping_element(employee_mapping, e1, e1.name) = createGuiElement("name");
get_mapping_element(employee_mapping, e1, e1.age) = createGuiElement("age");
}
In the code there is a Mapping, one per class. Each member is identified by its offset from the beginning of its enclosing class.
In general, you use macros for such purposes. They can generate any kind of code/wrappers that you'd like, letting you have the usual access to your data, but also adding stuff you want/need. It ain't pretty, but it works.
There are some template libraries that can help here, like Boost.Fusion or Boost.Hana, but, you can also roll your own here if you don't have a use for their advanced features (which come with the long compilation price tag).
Also, if you can focus on a particular GUI framework, they have some support for such things. For example, Qt has its own "meta object" compiler.
You could try a template for this?
e.g.
template <typename T>
class GuiItem : public T {
map<MemberHandle, GuiElement*> guiHandles;
}
GuiItem<A> guiA;
guiA.x = 123;
guiA.y = "y";
guiA.guiHandles[handle] = element;
I'm not sure I understand the other requirements so this way may not work for you.

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.

C++ what is proper way to include STL container in my class?

To begin with, I'm new to C++/OOP.
I want to include a std::map in my class and am wondering about how to provide users of my class the map typedefs and capabilities. Do I need to do as in the simple example below? (I've only shown a subset to indicate what I'm trying to do)
It doesn't feel right that I have to do this for any class where I've included a container (even for a subset of map methods).
It also seems like a class maintenance issue (e.g. might not need some map method today, but it becomes needed in the future)
p.s. aside from replying to this question, any other corrections/feedback to the example below are appreciated.
#include <map>
#include <string>
class Inventory {
public:
typedef std::string key_type;
typedef std::string mapped_type;
typedef std::map<key_type, mapped_type>::value_type value_type;
Inventory() { }
Inventory(int lotNum) : lotNum_(lotNum) { }
void insert(const value_type& el) { cars_.insert(el); }
//
// TODO: iterators, erase, etc
//
private:
int lotNum_;
std::map<key_type, mapped_type> cars_;
};
int main() {
Inventory ourCars(1);
ourCars.insert( Inventory::value_type( "BMW","ABC123" ) );
return 0;
}
Here is how I would think about this problem. Think of your class interface and implementation separately. The user shouldn't need to know what you're doing behind the scenes - what containers you're using etc. Your class itself should have some functionality that you provide through its interface. I'm not sure what your class is supposed to do, but if you want a function to insert two strings you should just provide that function. That's your starting point. Then you decide that you're going to store your strings in a map or whatever. In summary, the types that go into the map will be decided by your class interface. What you're doing is the opposite - deciding how you're implementing it and then exposing the types of your map in the interface.