Using ternary operator on std::map with std::greater additional argument - c++

I have two std::maps. One uses std::greater in the constructor so it is sorted the opposite direction:
std::map<key, value> map1;
std::map<key, value, std::greater> map2;
Currently I have two functions, one per map, each iterating over the elements and processing. However, given the processing logic is the same (only the map iteration direction is different) I wanted to replace these two functions with one:
template<bool useMap1>
void combinedFunc()
{
std::map<key, value>& map = useMap1 ? map1 : map2;
std::map<key, value>::iterator iter = map.begin();
// A fair amount of code iterating over the elements, hence wishing to combine
}
However, the compiler is rightfully saying that map1 and map2 are incompatible types.
Is there a way to reuse the code, even with std::greater?

Is there a way to reuse the code, even with std::greater?
Here's one way.
Create two overloaded functions for dealing with the two maps.
Move the core logic of dealing with the items of the maps to another function that works with iterators.
template <typename Iterator>
void coreFunction(Iterator start, Iterator end) { ... }
// For map1
void functionForMap(std::true_type dummyArgument)
{
coreFunction(map1.begin(), map1.end());
}
// for map2
void functionForMap(std::false_type dummyArgument)
{
coreFunction(map2.begin(), map2.end());
}
template<bool useMap1>
void combinedFunc()
{
functionForMap(std::integral_constant<bool, useMap1>());
}
Still simpler -- this requires only the first function.
template<bool useMap1>
void combinedFunc()
{
useMap1 ? coreFunction(map1.begin(), map1.end()) : coreFunction(map2.begin(), map2.end());
}

Instead of a template argument that implies what type to use, why not be direct and specify which type to use? Something like:
template<class M>
void combinedFunc(const M & map) // Drop "const" if necessary
{
M::iterator iter = map.begin();
// A fair amount of code iterating over the elements, hence wishing to combine
}
The caller is then responsible for specifying the map.
combinedFunc(map1); // The template parameter should be deducible.
This has the benefit of not locking your template to only two specific maps. On the downside, the caller has to know about map1 and map2. This might be undesirable if combinedFunc is part of a public interface, while the maps are not. In that case, you could write a wrapper function for the interface. Something simple like the following should work.
void publicFunc(bool useMap1)
{
if ( useMap1 )
combinedFunc(map1);
else
combinedFunc(map2);
}
Note that this calls two distinct functions even though the syntax makes it look like the same one. (You cannot do something like combinedFunc(useMap1 ? map1 : map2);.)

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

standard interface of iterator::operator* that return more than T& and std::pair

Iterator of each datastructure has different type of return value of operator*() e.g. :-
Most array-like DataStructure<T> : return T&.
std::unordered_map<K,T> : return std::pair<const K, T>&.
const std::unordered_map<K,T> : return const std::pair<K, T>&.
What should be the datatype if my iterator::operator*() want to return something more complex (std::pair is not enough)?
Example
I have a custom 3D datastructure Map3D<T> that is like a map (int,int,int)->T.
To achieve the above requirement, I create a new class Bundle3D<T>.
template<class T>class Bundle3D {
//getInternalIndex1D()
//getCoordinate()
//getValue()
};
The Map3D<T>'s iterator::operator* would have signature like :-
Bundle3D<T> iterator::operator*(){ ... }
Its usage is like :-
Map3D<float> map;
for(auto& ele:map){ //"ele" has some special type named "Bundle"
int keyInternal1DIndex=ele.getInternalIndex1D();
Vector3Int& key=ele.getCoordinate();
float& value=ele.getValue();
}
It works good, but I think my code is not standardized.
In other words, Bundle3D<T>, getInternalIndex1D(), getCoordinate() and getValue() is blindly named by me.
In real case, I have created a lot of custom data-structures that generate such strange iterator.
Question
Is there any std::/standard type of return-value of iterator::operator*(), when T& and std::pair is not enough?
I have doubted about this for several months, but feel very reluctant to ask it.
If this question need improvement, please comment.
Edit
(clarify the word standardized - this part is my subjective notion.)
I feel that all types of standard collection in most language, e.g. :-
java.util.Collection/ArrayList in Java
std::unordered_map/vector in C++
Iterators of all of them have signatures of function getValue() or operator* that return either T or StandardPair<index,T> - no other types.
For many years, I am convinced that it is a rule or a strong convention/tradition that I really should obey.
There must be a reason.
However, I am not sure what it is, because I am probably very new to C++.
If I design my software to return something strange (e.g. Bundle3D<T> in the above example), I think I will get punished hard from the unconventional design. (e.g. not have .first field)
What you have right now is okay. I would just specify one thing that I think isn't very C++-ish and may in fact harm your standardization options in the future.
It's the getters. Obviously you have deep roots in Java, and the concept of public members is abhorred in Java programming, so much so that the concept of "beans" exists. I don't intend to knock on Java here, it's a nice language with its own nice idioms.
But this is C++, with it's own programming idioms. You obviously noticed the direct access to the contents of std::pair. It's like that for a reason. A pair is just two items packed together, that's the sum of its behavior. Getters would just ,well, get in the way. :)
There's no need for them, because we aren't dealing with an "abstraction" of two items bundled together, but instead we really do have a concrete, honest to god, bundle1.
Obviously we can have bundles of more than two items. That's why we have std::tuple. Now while it's true that all access to a tuple is through a non-member function called get, that's simply because there is no way to give names to members of an arbitrarily sized bundle. get still returns a reference to the element, so you retain direct access into the bundle.
This long winded exposition is important, because an upcoming C++1z feature, called "Structured Bindings", relies on the standard behavior of tuples and pairs, as well as how C++ programmers see aggregates. Under this feature, an iteration over a map, will look like this:
#include <map>
#include <iostream>
std::map<char const*, int> foo()
{
return {
{ "foo", 3 },
{ "bar", 7 },
{ "baz", 1 },
};
}
int main() {
for (auto [key, val] : foo()) {
std:: cout << "( " << key << ", " << val << " )\n";
}
return 0;
}
Live example
And the same extends to any user defined bundle of data. Your own return value type in the post can be bound similarly, if the members are public:
struct Vector3Int {};
template<class T>
struct Bundle3D {
int internal_index_id;
Vector3Int const &coord;
T &value;
};
int main() {
Vector3Int vec;
float val;
Bundle3D<float> bundle{ 1, vec, val };
auto[ idx_id, coord, value] = bundle;
// coord = {}; // compile error since coord gets the cv qualifer
}
Live example
So my suggestion is, leave the getters to your Java code, and use aggregates as bundles of data for C++.
1 An aggregate, to be more formal.
I'm going to assume that your Map3D is a spacial co-ordinate to value container.
I would return a std::pair<const Vector3Int, T>&, and not bother with getInternalIndex1D as part of the return. That can be left as a function Vector3Int -> int.
Have a look at UnorderedAssociativeContainer for the sorts of members that would be useful to define
e.g.
template <typename T>
class Map3D
{
using key_type = Vector3Int;
using mapped_type = T;
using value_type = Bundle3D<T>; // Key, Value, Internal1DIndex
using reference = Bundle3D<T> &;
using pointer = Bundle3D<T> *;
using hasher = /*Function object that calculates Internal1DIndex*/
using key_equal = std::equal<Vector3Int>
... iterators, const_* definitions, etc
}

std::map: Use only part of keytype for comparison and finding

I have a map that uses pairs of some datatype KT as keys to map to a matrix type, i.e. sth. like
std::map<std::pair<KT,KT>, MatType, PairCompare>
For comparison I only need the first element of the pair, so PairCompare is very simple
struct PairCompare
{
bool operator()(const std::pair<KT,KT>& lhs,const std::pair<KT,KT>& rhs) const
{return lhs.first<rhs.first;}
};
I would however like to use the whole pair as a key, as I constantly need the second element in operations while iterating through the map.
Sometimes, I also need to find a map entry based on a single KT only. Of course I should use a pair of KT in the find() routine, but I would like to avoid creating a dummy pair of KT, as I have to do this many times and that could get expensive. I would like to use something like
std::map<std::pair<KT,KT>, MatType, PairCompare> mymap;
KT mykey = // ... some implementation of KT;
// fill map
auto it = mymap.find(mykey); // <- will not work of course, but what I would like to use
auto it = mymap.find(std::pair<KT,KT>(mykey,mykey)); // <- what I am using so far (creating a dummy pair)
Mykey can in general be both lvalue and rvalue (in my application).
Is there any way of defining a different type of key that contains two KT instances and only uses one for map ordering and also enables finding by single KTs that works straight forward? Can it be done with some special comparison object? Maybe there is also a smart way of getting around using pairs of KT as Key at all, but still enabling access to the second KT in map iterations?
Thanks for your help!
P.S.: to be precise, as KT I am using
typedef std::vector<int> KT
Your problem is that you think of keys as "pair of X,Y". Think of the key as "an object that supports this and that operations":
template<typename K1, typename K2>
class Key
{
K1 v1_;
boost::optional<K2> v2_;
public:
Key(K1 v1): v1_{ std::move(v1) }, v2_{} {}
Key(K1 v1, K2 v2): v1_{ std::move(v1) }, v2_{ std::move(v2) } {}
bool operator==(const Key<K1,K2>& other)
{
if(!v2_ || !other.v2_)
return v1_ == other.v1_;
return std::tie(v1_, *v2_) == std::tie(other.v1_, *other.v2_);
}
// implement other comparisons, as required
};
using KeyType = Key<int,std::string>;
std::map<KeyType, MatType> YourMap;
// add key comparable by first element:
YourMap[KeyType{0}] = MatType{}; // match KeyType{0, "any string"}
// add key comparable by both elements:
YourMap[KeyType{1, "test"}] = MatType{}; // match KeyType{1, "test"}
Attempting to force the key to be a pair here complicates the problem.

C++03: Is there a way to make a type that will compile to different types every time it is included in a template parameter?

I am trying to achieve something like this:
typeof(vector<MyStrangeType>) != typeof(vector<MyStrangeType>)
I.e. I want this type to produce a different type every time it is included as a template parameter.
An example of where I might practically want this is to avoid undefined behavior in this situation:
class DeviousHashAlg {
private:
int seed;
public
DeviousHashAlg() {
seed = rand();
}
template<class TYPE>
size_t operator()(TYPE key) {
return hash<TYPE>()(key) * seed
}
}
unordered_map<SomeKey, SomeValue, DeviousHashAlg> map1;
unordered_map<SomeKey, SomeValue, DeviousHashAlg> map2;
map1 == map2; // Currently undefined
It is undefined behavior to compare these maps, since the values inside will not have hashed to the same bucked. What I would like to do is make this undefined behavior instead a compile time error. This is why I want DeviousHashAlg to produce a different type every time it is included in a template like unordered_map, so that we won't be allowed to use ==.
Is this even possible? I'd prefer to use language support if possible, though I suspect some pre-processing black magic may be the only solution.
You may use the macro __COUNTER__ and make your class template as follow:
template <std::size_t N>
struct DeviousHashAlg
{
/* Your code */
};
#define UNIQUE_DeviousHashAlg DeviousHashAlg<__COUNTER__>
And then, for
unordered_map<SomeKey, SomeValue, UNIQUE_DeviousHashAlg> map1;
unordered_map<SomeKey, SomeValue, UNIQUE_DeviousHashAlg> map2;
map1 and map2 will have different type.

boost Filter iterator with different predicates

I'm trying to implement a method which returns a boost::filter_iterator pair (begin, end).
I would like this method to be customizable in terms of filtering, but I don't know how I could sort this out since when I typedef the filter iterator range I have to hardcode the predicate I want to use and I cannot choose it depending on the parameter the method receives in input.
I would like to have something like this :
enum FilterType
{
FilterOnState = 0,
FilterOnValue,
FilterOnSize,
FilterOnWhatever...
}
typedef boost::filter_iterator<PredicateStruct, std::list<Object>::iterator> filter_iterator;
std::pair<filter_iterator, filter_iterator> filterObjects(FilterType filterType);
I thought about a possible template solution as well, but I would need the client to access predicates implementation and instance the one suiting his needs before calling the filter, he'd almost do all the job himself : that's why I'd like best the enum based solution.
template<typename P>
std::pair<boost::filter_iterator<P, std::list<Object>::iterator>,
boost::filter_iterator<P, std::list<Object>::iterator>> filterObjects(P& predicate);
Would a predicate "base class" be a possible solution for the enum based implementation ?
Thanks a lot in advance!
Giacomo
Why not simply provide predefined predicates instead of enum values?
struct predef_predicate{
predef_predicate(FilterType f)
: filt(f) {}
template<class T>
bool operator()(T const& v) const{
// filter in whatever way...
}
private:
FilterType filt;
};
namespace { // guard against ODR violations
predef_predicate const filter_state(FilterOnState);
predef_predicate const filter_values(FilterOnValue);
// ...
}
And then, instead of reinventing the wheel, just use Boost.Range's filtered adaptor.
#include <vector>
#include <iterator>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorith/copy.hpp>
int main(){
std::vector<int> v;
// fill v
std::vector<int> filtered;
boost::copy(v | boost::adaptors::filtered(filter_values),
std::back_inserter(filtered));
}
And with C++11, the act of creating a predicate becomes even easier thanks to lambdas.