Trying to (slightly) generalize C++ template. Associative container Key:Value Inversion - c++

The goal of the function template below is to take any unordered_map and to produce a new unordered_map with the key_type and mapped_type inverted.
The function below works for std::unorderd_map. I'd like it to additionally work for EITHER std::unordered_map and any stl hashmap analog.
An additional benefit I'd like to maintain is that when calling the function, if default behavior is desired, auto inversion = InvertHashMap(someIntStringMap) works with no template arguments. However, if I do provide the valid initial template arguments, I can override the default hasher for example used to build the inverted map.
I am having profound difficulty making the container generic, while still providing default-able template arguments based on that container's 5 template arguments. As soon as I make the container itself a template argument, overload resolution fails and the compilation fails.
I've entertained making the associative container the only template argument, but then the ability to affect the output container's template arguments are lost, at least in the way they can be explicitly templated in my non-flexible example.
#include <unordered_map>
#include <utility>
#include <functional>
#include <memory>
template <typename InKeyType,
typename InValueType,
typename InHasher,
typename InEq,
typename InAlloc,
typename OutHash = std::hash<InValueType>,
typename OutEq = std::equal_to<InValueType>,
typename OutAlloc=std::allocator<std::pair<constInValueType,InKeyType>>>
std::unordered_map<InValueType, InKeyType, OutHash, OutEq, OutAlloc>
InvertMap(const std::unordered_map<InKeyType, InValueType, InHasher, InEq, InAlloc>& source)
{
std::unordered_map<InValueType, InKeyType, OutHash, OutEq, OutAlloc> outMap;
for (const auto& sourceKVPair : source)
outMap[std::get<1>(sourceKVPair)] = std::get<0>(sourceKVPair);
return outMap;
}
//in a .cpp
unordered_map<int,string> um;
auto newUM = InvertHashMap(um); //works well; newUM::key_type is string
I'd like to be able to call InvertMap(aIntStringUnorderedMap) and ALSO InvertMap< int, string, hash<int>, ..., MyCustomStringHasher>(aIntStringHashMapLikeClass)//producing a HashMapLikeClass<string,int, MyCustomStringHasher,...defaults>
TLDR: How do I introduce an argued container to a template, and also its template parameters, without changing call-site semantics?
Edit. This is my attempt to use the container as the only template argument.
template <typename AssocCont>
auto InvertCompliantHashMapThatIsntSTDUnorderedMap(const AssocCont&)
{
typedef typename AssocCont::key_type InKeyType;
typedef typename AssocCont::mapped_type InMappedType;
typedef typename AssocCont::value_type InPairConstruct;
typedef typename AssocCont::hasher InHasher;
typedef typename AssocCont::key_equal InEq;
//...
}
//But now there is no external means of desginating the new container's hasher,equality functor etc...
//And as it turns out, I cant even instantiate a new return object from AssocCont<InKeyType,InMappedType> since it is a distinct and unknown type
AssocCont<InMappedType,InKeyType> outmap = AssocCont<InMappedType,InKeyType>(); // nope. equivalent to object<key,value><otherkey,othervalue>()
DOUBLE EDIT: in my haste to provide an example, I chose std::map as an alternate paramater example, which i realize doesn't have a hasher, nor five template arguments. So the basis of my question is still trying to diversify this function, but specifically for arguments that have five template arguments of their own with compatible behavior.... I have edited my post to mitigate this oversight.

I feel like this might be better implemented in a manner similar to the standard algorithms library. In other words, design your inversion function to take a range of iterators into the input container and an iterator into the output container. It will be simpler to implement and provide greater flexibility to users. Furthermore, it will be somewhat independent of the container type as long as the input and output iterators satisfy certain conditions (imposed by concepts perhaps). Here is an example which may not be exactly what you want but you can probably modify it to fit your needs:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <unordered_map>
namespace
{
template <class InputIt, class OutputIt>
void inverse_map(InputIt start, InputIt stop, OutputIt d_first)
{
while(start != stop)
{
*d_first = {start->second, start->first} ;
++d_first ;
++start ;
}
}
} // anonymous namespace
int main()
{
std::map<int, std::string> map_1 {{1, "foo"}, {2, "bar"}, {3, "foo"}} ;
std::unordered_map<std::string, int> map_2 ;
//
// Or, you can use:
//
// std::unordered_map<std::string, int, MyCustomHasher> map_2 ;
//
inverse_map(map_1.begin(), map_1.end(), std::inserter(map_2, map_2.end())) ;
for(const auto& [key, value]: map_2) // requires C++17
std::cout << key << ": " << value << "\n" ;
return 0;
}
Output:
bar: 2
foo: 1
Try it out online here.

Related

C++: Can't propagate polymorphic_allocator with scoped_allocator_adaptor

I have a vector<vector<int>> and want the entire memory (i.e., of both the outer and the inner vector) to be taken from a memory_resource. Here is a stripped down example, first the boring part:
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
#include <iostream>
#include <string>
#include <vector>
// Sample memory resource that prints debug information
class MemoryResource : public boost::container::pmr::memory_resource {
void* do_allocate(std::size_t bytes, std::size_t alignment) {
std::cout << "Allocate " << bytes << " bytes" << std::endl;
return malloc(bytes);
}
void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) { free(p); }
bool do_is_equal(const memory_resource& other) const noexcept { return true; }
};
This is the part that I am interested in:
template <typename T>
using Alloc = boost::container::pmr::polymorphic_allocator<T>;
// using Alloc = std::allocator<T>;
template <typename T>
using PmrVector = std::vector<T, boost::container::scoped_allocator_adaptor<Alloc<T>>>;
using Inner = PmrVector<int>;
int main() {
MemoryResource resource{};
PmrVector<Inner> v(1000, Alloc<Inner>{&resource});
// PmrVector<Inner> v(1337, Alloc<Inner>{});
v[0].resize(100);
}
This gives me a lengthy compiler warning, essentially saying that it can't find a constructor for the inner vector.
If, instead of the polymorphic allocator, I use a regular allocator (e.g., std::allocator - see the lines that are commented out), everything seems to work.
The gcc error message is a bit better than that of clang:
/usr/local/include/boost/container/allocator_traits.hpp:415:10:
error: no matching function for call to '
std::vector<int, polymorphic_allocator<int> >::vector(
scoped_allocator_adaptor<...>&, polymorphic_allocator<...>&
)
'
Why would boost try to construct a vector by passing the allocator twice?
Also, here is a version that uses STL (experimental) instead of boost. That one gives an actual error message "construction with an allocator must be possible if uses_allocator is true", but that doesn't help me either.
Maybe I am understanding something conceptually wrong. Is this the way to do it or is there a better way to solve the original problem?
Argh. The explanation is hidden in std::experimental::pmr::polymorphic_allocator::construct:
This function is called (through std::allocator_traits) by any
allocator-aware object, such as std::vector, that was given a
std::polymorphic_allocator as the allocator to use. Since
memory_resource* implicitly converts to polymorphic_allocator, the
memory resource pointer will propagate to any allocator-aware
subobjects using polymorphic allocators.
So it turns out that polymorphic allocators automatically propagate. That also explains why the allocator is passed twice in the gcc error message.
Here is a working version:
template <typename T>
using Alloc = std::experimental::pmr::polymorphic_allocator<T>;
template <typename T>
using PmrVector = std::vector<T, Alloc<T>>;
using Inner = PmrVector<int>;
int main() {
MemoryResource resource{};
PmrVector<Inner> v(1000, Alloc<Inner>{&resource});
v[0].resize(100);
}
And here is the information that I would have need a couple of hours ago:
How do I use polymorphic_allocator and scoped_allocator_adaptor together?
You don't. Make sure that all inner containers also use polymorphic allocators, then the memory resource will be handed down automatically.

How to create iterator without type names?

For example I have a std::map<int, string> _m; and I want to iterate through it.
So I have to write something like this: std::map<int, string>::iterator it = _m.begin().
The question is whether it is possible to create that iterator without using type names. Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?
UPDATE
I forgot to say that I've to use old C++ standard.
You're after the auto keyword:
auto it = _m.begin();
Compiler knows the type of _m at the moment of creation of iterator, so why do I need to write those types myself?
Yes, this is the exact logic that lead to the introduction of auto.
If you cannot use C++11, you're stuck with things like typedef. The whole reason the new standard introduced auto is because of the exact problem you're facing - it's awkward to have to manually write out long type names all the time.
typedef std::map<int, string>::iterator map_itr;
map_itr it = _m.begin();
Since you specify that you're locked back in time to C++98, then about the best you have is whatever black magic is behind BOOST_AUTO.
#include <boost/typeof/typeof.hpp>
#include <map>
#include <string>
int main()
{
std::map<int, std::string> m;
BOOST_AUTO(it, m.begin());
}
BOOST_FOREACH was created as a similar thing for dealing with loops without having to specify iterator types.
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
// populate v...
BOOST_FOREACH(int const &i, v)
{
std::cout << i << "\n";
}
}
Actually it is possible by using template function:
template <typename ITERATORTYPE> void myfunc(ITERATORTYPE it) {
//.. do whatever you want with your it
}
Then just invoke the template:
myfunc(_m.begin());
If you're stuck to C++03, there's no way to refer to the type without spelling it out if you really need it. The best you could do is introduce a typedef (or more) so that you only have to type the long type once:
typedef std::map<int, string> TypeOfM;
typedef TypeOfM::iterator MIterator;
TypeOfM _m;
However, when you use standard library algorithms, you don't have to name the iterators explicitly:
std::for_each(_m.begin(), _m.end(), /* a functor */);
If Boost is an option, and you really only want iteration, you could also use Boost.Foreach. Unfortunately, that would still need a typedef, because the value_type of map is a pair and thus contains a , which would trip up the preprocessor:
typedef std::pair<const int, string> Pair;
BOOST_FOREACH(const Pair &p, _m)
{
// Do whatever you need
}
Since you're trying to iterate over it, you may try one of the <algorithm>s such as std::for_each and pass a function
The best general way is by using C++11's auto keyword as type. In later versions this can be done even better with range-bsed loops without any type information.
for (it : _m) {
/* ... */
}
If you are stuck to old versions the only way to shorten the typename would be to create a template. This might make it more complex than writing the name, though. Something along those lines:
template <typename T>
void do_foo(T it, T end) {
for (; it < end; ++it) {
/* ... */
}
}
do_foo(_m.begin(), _m.end());
If wrapping your algorithm isn't the way you can also use a typedef to shorten it, but then you still have to type the name once.

Boost: Vector of Distributions with any

Dear Stack Exchange Experts,
I am trying to set up a class (multivariate distribution function) that stores boost distributions in a std::vector (marginal distribution functions).
While this is possible using boost::variant (see my question: Boost: Store Pointers to Distributions in Vector), I also gave boost::any a try.
The reason being that with variant I have to hard-code the potential types (marginal distributions) when setting up the variant and I wanted to avoid this.
While the different implemented distribution classes do not share a common parent class, there are functions such as boost::math::cdf or boost::math::pdf that can be applied to all distributions, and that I want to apply iterating over the std::vector.
Working with any I produced the code below (which is running fine), but now I have the problem that the function any_cdf needs to check the types.
While I circumvented hard-coding the types when setting up the vector (as for variant) I now need to hard-code the types in the any_cdf function (while the solution with variants can handle the application of the cdf function via a templated visitor function, and thus without any type specifications) which means lots of code to manage, lots of if statements...
However, the logic does not change at all (I cast the type, then apply the cdf function in all if statements), and I wouldn't really care how the function behaves if something other than a boost distribution gets stored in the list.
So is there any chance to have my cake and eat it, meaning not being forced to hard-code the casting type of the distribution in any_cdf (much like a templated visitor function for variants)?
Thanks so much for your help, H.
P.s. if this is not feasible, would I generally be better of with boost::any or boost::variant in this situation?
#include <boost/math/distributions.hpp>
#include <boost/any.hpp>
#include <vector>
#include <iostream>
#include <limits>
//template function to apply cdf
template<class T> T any_cdf(boost::any a, T &x){
//declare return value
T y;
//cast any with hardcoded types
if (a.type() == typeid(boost::math::normal_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::normal_distribution<T> >(a),x);
} else if (a.type() == typeid(boost::math::students_t_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::students_t_distribution<T> >(a), x);
} else {
//return NaN in case of failure or do something else (throw exception...)
y = std::numeric_limits<T>::quiet_NaN();
}
return(y);
}
int main (int, char*[])
{
//get distribution objects
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//use any to put just any kind of objects in one vector
std::vector<boost::any> vec_any;
vec_any.push_back(s);
vec_any.push_back(t);
//evaluation point and return value
double y;
double x = 1.96;
for (std::vector<boost::any>::const_iterator iter = vec_any.begin(); iter != vec_any.end(); ++iter){
y = any_cdf<double>(*iter,x);
std::cout << y << std::endl;
}
return 0;
}
Edit: Concerning the comments any seems not to be the easiest/best choice for the task at hand. However for completeness reasons a visitor like implementation for boost::any is discussed at:
visitor pattern for boost::any
Note See my older answer for a discussion of solutions a vector and boost::any vs. boost::variant.
If you don't actually need a dynamic vector of distributions - but just want to apply a statically known list of distributions, you can "get away" with a tuple<> of them.
Now, with a bit (well, a lot) of magic from Phoenix and Fusion, you can "just" adapt the cdf function as a Lazy Actor:
BOOST_PHOENIX_ADAPT_FUNCTION(double, cdf_, boost::math::cdf, 2)
In which case an equivalent extended code sample shrinks to: See it Live On Coliru
int main()
{
typedef boost::tuple<bm::normal, bm::students_t> Dists;
Dists dists(bm::normal(), bm::students_t(1));
double x = 1.96;
boost::fusion::for_each(dists, std::cout << cdf_(arg1, x) << "\n");
std::cout << "\nComposite (multiplication):\t" << boost::fusion::accumulate(dists, 1.0, arg1 * cdf_(arg2, x));
std::cout << "\nComposite (mean):\t\t" << boost::fusion::accumulate(dists, 0.0, arg1 + cdf_(arg2, x)) / boost::tuples::length<Dists>::value;
}
Whoah. That's... hardly 6 lines of code :) And the best part is it's all c++03 compatible already.
Update This is the answer assuming a vector and boost::any vs. boost::variant. If you can use a tuple<> see my other answer
You will end up hardcoding the potential types one way or another.
With variant, you can group and hide the complexities by using visitor:
struct invoke_member_foo : boost::static_visitor<double>
{
template <typename Obj, typename... Args>
double operator()(Obj o, Args const&... a) const {
return o.foo(a...);
}
};
This can be applied to your variant like
boost::apply_visitor(invoke_member_foo(), my_variant);
With boost any, you'd do the typeswitching the boring and manual way:
if (auto dist1 = boost::any_cast<distribution1_t>(&my_any))
dist1->foo();
else if (auto dist2 = boost::any_cast<distribution2_t>(&my_any))
dist2->foo();
else if (auto dist3 = boost::any_cast<distribution3_t>(&my_any))
dist3->foo();
IMO this is clearly inferior for maintainability e.g.
you can't easily extend the type list with an element type that is similar enough to satisfy the same concept and have it support - you'll need to add cases to the type-switch manually (and if you don't - you're out of luck, there is no error and you'll have (silent) bugs. With variant you'll just get a compile error whenever your visitor doesn't handle your type.
this work ^ (the type switching) gets duplicated for each operation that you want to implement across the board. Of course, you can implement the type-switch once, and provide the actual implementation as a functor, but at that moment you'll have implemented the exact equivalent of a static_visitor as I showed for the variant, except with far less efficient implementation.
boost::any can only contain values that are CopyConstructible. Boost variant can even contain references (e.g. boost::variant<dist1_t&, dist2_t&>) and has (some) move-semantics support
In short, boost::any saves on time thought in advance, but all it does is shift the work to the call-sites.
On a positive note, let me share with you an idiom I like, which makes visitors accessible as ordinary free functions. Let's rewrite your any_cdf function for the variant:
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist& dist, T& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T> T var_cdf(VarDist<T> a, T &x)
{
static detail::var_cdf_visitor<T> vis;
return boost::apply_visitor(
boost::bind(vis, ::_1, boost::ref(x)),
a);
}
A full running program can be found Live On Coliru
Demo Listing
#include <boost/bind.hpp>
#include <boost/math/distributions.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <limits>
#include <vector>
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist const& dist, T const& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T, typename... Dist> T var_cdf(boost::variant<Dist...> const& a, T const& x) {
return boost::apply_visitor(boost::bind(detail::var_cdf_visitor<T>(), ::_1, x), a);
}
int main()
{
namespace bm = boost::math;
typedef std::vector<boost::variant<bm::normal, bm::students_t> > Vec;
Vec vec { bm::normal(), bm::students_t(1) };
//evaluation point and return value
double x = 1.96;
for (auto& dist : vec)
std::cout << var_cdf(dist,x) << std::endl;
}
Actually, though I used a bit of c++11, this could be made even prettier using some c++1y features (if your compiler has them).
And lastly, you can make work for c++03 too; it would just require more time than I currently have to throw at it.
What about:
int main (int, char*[])
{
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
typedef std::vector<boost::function<double (double)> > vec_t;
vec_t vec_func;
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(s), _1));
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(t), _1));
//evaluation point and return value
double y;
double x = 1.96;
for (vec_t::const_iterator iter = vec_func.begin(); iter != vec_func.end(); ++iter){
y = (*iter)(x);
std::cout << y << std::endl;
}
return 0;
}
Binding argument to a function template can be tricky though.

Initializing stl classes with template parameters

I am trying to do declare a stl map with template parameters like so:
( assume T as typename like so : template <class T>)
map<T, T> m; ( in .h file )
It compiles fine. now in my cpp file, when I want to insert into the map, i am not able to. The only methods i get on intellisense are "at" and "swap" methods.
Any ideas? Anyone please?
Thanks in advance.
here is sample code:
#pragma once
#include <iostream>
#include <map>
using namespace std;
template <class T>
class MySample
{
map<T, T> myMap;
//other details omitted
public:
//constructor
MySample(T t)
{
//here I am not able to use any map methods.
//for example i want to insert some elements into the map
//but the only methods I can see with Visual Studio intellisense
//are the "at" and "swap" and two other operators
//Why???
myMap.
}
//destructor
~MySample(void)
{
}
//other details omitted
};
The usual ways to insert key-value pairs into a std::map are the index-operator syntax as well as the insert function. I'll assume std::string for keys and int for values for the sake of the example:
#include <map>
#include <string>
std::map<std::string,int> m;
m["hello"] = 4; // insert a pair ("hello",4)
m.insert(std::make_pair("hello",4)); // alternative way of doing the same
If you can use C++11, you may use the new uniform initialization syntax instead of the make_pair call:
m.insert({"hello",4});
And, as said in the comments, there is
m.emplace("hello",4);
in C++11, which constructs the new key-value pair in-place, rather than constructing it outside the map and copying it in.
I should add that since your question is actually about initialization, rather than inserting fresh elements, and given that indeed you do this in the constructor of MyClass, what you should really do (in C++11) is this:
MySample(T t)
: myMap { { t,val(t) } }
{}
(Here I assume there is some function val which generates the value to store for t in the map.)

C++ passing vector of unique_ptrs as parameters to corresponding element of another equal-length vector (especially parallelly)

I have:
vector of unique_ptrs of ObjectA
vector of newly default constructed vector of ObjectB, and
a function in Object B that has signature void f(unique_ptr<ObjectA> o).
(word Object omitted from here on)
How do I do Bvec[i].f(Avec[i]) for all 0 < i < length in parallel?
I have tried using transform(Bvec.begin(), Bvec.end(), A.begin(), B.begin(), mem_fun_ref(&B::f)), but it gives a bunch of errors and I'm not sure if it would even pass the right A as parameter, let alone allow me to move them. (&B::f(A.begin()) would not work as the last parameter either.
I have also thought of using for_each and then a lambda function, but not sure how to get the corresponding element. I thought of incrementing a counter, but then I don't think that parallelizes well (I could be wrong).
I can, of course, use a for loop from 0 to end, but I am pretty sure there is a simple thing I'm missing, and it is not parallel with a simple for loop.
Thanks.
Here is a non-parallel implementation using a handmade algorithm. I'm sure someone more versed in the functional could come up with a more elegant solution. The problem with transform is, that we cannot use it with functions that return void and I can't remember another stdlib function that takes two ranges and apply them to each other. If you really want to parallelize this, it needs to be done in the apply_to function. Launching an async task (e.g. std::async(*begin++, *begin2++) could work, although I have no experience with this and cannot get it to work on gcc 4.6.2.
#include <iterator>
#include <memory>
#include <vector>
#include <algorithm>
#include <functional>
// this is very naive it should check call different versions
// depending on the value_type of iterator2, especially considering
// that a tuple would make sense
template<typename InputIterator1, typename InputIterator2>
void apply_to(InputIterator1 begin, InputIterator1 end, InputIterator2 begin2) {
while(begin != end) {
(*begin++)(*begin2++);
}
}
struct Foo {
};
struct Bar {
void f(std::unique_ptr<Foo>) { }
};
int main()
{
std::vector< std::unique_ptr<Foo> > foos(10);
std::vector< Bar > bars(10);
std::vector< std::function<void(std::unique_ptr<Foo>) > > funs;
std::transform(bars.begin(), bars.end(), std::back_inserter(funs),
// non-const due to f non-const, change accordingly
[](Bar& b) { return std::bind(&Bar::f, &b, std::placeholders::_1); });
// now we just need to apply each element in foos with funs
apply_to(funs.begin(), funs.end(), std::make_move_iterator(foos.begin()));
return 0;
}