boost range weak_ptr - c++

I have a map where the value is a weak pointer. This works:
While I can write this:
for_each( IFoo::foo_wptr obj, objects | range::map_values ) {
IFoo::foo_ptr myObj = obj.lock();
if( myObj ) myObj->notify();
}
I'd much rather have a new range that transforms to a locked shared pointer. Something like this:
for_each( IFoo::foo_ptr obj, objects | range::map_values | range::locked ) {
if( obj ) obj->notify();
}
however, I've been unable to figure out what that transform should look like; or if it should even be a transform.
Does anyone have an idea? I'm convinced this pattern may quite common.

Here's an example that I literally just threw together:
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/foreach.hpp>
#include <map>
#include <vector>
struct weak_ptr_locker
{
template <typename Sig>
struct result;
template <typename F, typename T>
struct result<F(boost::weak_ptr<T>&)>
{
typedef boost::shared_ptr<T> type;
};
template <typename T>
boost::shared_ptr<T> operator()(const boost::weak_ptr<T>& pWeak) const
{
return pWeak.lock();
}
};
template<typename R>
struct lock_transform_range :
boost::iterator_range< boost::transform_iterator< weak_ptr_locker, typename boost::range_iterator<R>::type> >
{
private:
typedef boost::iterator_range< boost::transform_iterator< weak_ptr_locker, typename boost::range_iterator<R>::type> > base;
public:
typedef boost::transform_iterator< weak_ptr_locker, typename boost::range_iterator<R>::type > iterator;
lock_transform_range(R& r)
: base(iterator(boost::begin(r)), iterator(boost::end(r)))
{}
};
namespace detail
{
struct lock_transform_forwarder {};
}
template< class BidirectionalRng >
inline lock_transform_range<BidirectionalRng> operator | (BidirectionalRng& r, detail::lock_transform_forwarder)
{
return lock_transform_range<BidirectionalRng>(r);
}
template< class BidirectionalRng >
inline lock_transform_range<const BidirectionalRng> operator | (const BidirectionalRng& r, detail::lock_transform_forwarder)
{
return lock_transform_range<const BidirectionalRng>(r);
}
namespace
{
const detail::lock_transform_forwarder locked = detail::lock_transform_forwarder();
}
struct Foo
{
Foo(int i)
: i(i)
{}
int i;
void notify()
{
std::cout << i << std::endl;
}
};
int main(int argc, char* argv[])
{
typedef std::map<int, boost::weak_ptr<Foo> > Map;
typedef boost::shared_ptr<Foo> FooPtr;
Map objects;
std::vector<FooPtr> storage;
for (int i = 0; i < 10; ++i)
{
storage.push_back(boost::make_shared<Foo>(i));
objects[i] = storage.back();
}
using namespace boost::adaptors;
for_each(FooPtr obj, objects | map_values | locked)
{
if (obj)
obj->notify();
}
return 0;
}

Related

C++: Using pair of (cpp_int, int) integers as key in unordered_map (where cpp_int are boost multiprecision integers)

For my unordered map I would like to use as keys pairs of (cpp_int, int) where cpp_int are boost multiprecision integers:
#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>
using boost::multiprecision::cpp_int;
std::unordered_map<std::pair<cpp_int, int>, double> myMap
Searching on this site I have found many suggestions of using a custom hash function for std::pair<int,int> as keys, but I couldn't found how to deal with std::pair<cpp_int, int>.
Update: To clarify, I have tried a hash function I found on the web (for (int,int):
#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>
using boost::multiprecision::cpp_int;
typedef std::pair<cpp_int, int> MyPair;
struct MyHash {
public:
size_t operator()(MyPair x) const throw() {
size_t h = x.first * 1 + x.second * 100000;
return h;
}
};
void function()
{
std::unordered_map<MyPair, double, MyHash> M;
}
This doesn't compile:
error: cannot convert ‘boost::enable_if_c<true, boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void> >::type {aka boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_add, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, void, void, void>, boost::multiprecision::detail::expression<boost::multiprecision::detail::terminal, int, void, void, void>, int, void>}’ to ‘size_t {aka long unsigned int}’ in initialization
size_t h = x.first * 1 + x.second * 100000;
^
My question is: how to use pairs of (cpp_int,int) as keys in an unordered_map?
Thank you very much in advance!
Update 2:
Thanks to #sehe for pointing me to his answer (in which he provided a hash function for cpp_int). Combining with this answer (which shows how to combine two hash functions for a pair), I've come up with the following solution (it compiles fine, I'll need to test on my problem to see if it works):
#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/functional/hash.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <unordered_map>
using boost::multiprecision::cpp_int;
typedef std::pair<cpp_int, int> MyPair;
namespace mp_hashing {
namespace io = boost::iostreams;
struct hash_sink {
hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}
typedef char char_type;
typedef io::sink_tag category;
std::streamsize write(const char* s, std::streamsize n) {
boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
return n;
}
private:
size_t* _ptr;
};
template <typename T> struct hash_impl {
size_t operator()(T const& v) const {
using namespace boost;
size_t seed = 0;
{
iostreams::stream<hash_sink> os(seed);
archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
oa << v;
}
return seed;
}
};
}
namespace std {
template <typename backend>
struct hash<boost::multiprecision::number<backend> >
: mp_hashing::hash_impl<boost::multiprecision::number<backend> >
{};
}
struct pair_hash {
template <class T1, class T2>
std::size_t operator () (const std::pair<T1,T2> &p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(p.second);
// Mainly for demonstration purposes, i.e. works but is overly simple
// In the real world, use sth. like boost.hash_combine
return h1 ^ h2;
}
};
void function()
{
std::unordered_map<MyPair, double, pair_hash> M;
}
Yes, you took the Multiprecision hash I contributed earlier and added the hash for std::pair. I'm not a fan of handrolling the hash combination (good general hash combination is not trivial).
So I'd do the same with boost::hash_combine:
template <typename K, typename V>
struct hash<std::pair<K, V> >
{
size_t operator()(std::pair<K, V> const& pair) const {
size_t seed = std::hash<K>{}(pair.first);
boost::hash_combine(seed, pair.second);
return seed;
}
};
Live On MSVC RexTester
#include <iostream>
#include <iomanip>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_int/serialize.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/functional/hash.hpp>
namespace mp_hashing {
namespace io = boost::iostreams;
struct hash_sink {
hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}
typedef char char_type;
typedef io::sink_tag category;
std::streamsize write(const char* s, std::streamsize n) {
boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
return n;
}
private:
size_t* _ptr;
};
template <typename T> struct hash_impl {
size_t operator()(T const& v) const {
using namespace boost;
size_t seed = 0;
{
iostreams::stream<hash_sink> os(seed);
archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
oa << v;
}
return seed;
}
};
}
#include <unordered_map>
#include <boost/unordered_map.hpp>
namespace std {
template <typename backend>
struct hash<boost::multiprecision::number<backend> >
: mp_hashing::hash_impl<boost::multiprecision::number<backend> >
{};
template <typename K, typename V>
struct hash<std::pair<K, V> >
{
size_t operator()(std::pair<K, V> const& pair) const {
size_t seed = std::hash<K>{}(pair.first);
boost::hash_combine(seed, pair.second);
return seed;
}
};
}
int main() {
using boost::multiprecision::cpp_int;
std::unordered_map<std::pair<cpp_int, int>, int> m {
{ { cpp_int(1) << 111, -1 }, 1 },
{ { cpp_int(2) << 222, -2 }, 2 },
{ { cpp_int(3) << 333, -3 }, 3 },
};
for (auto& p : m)
std::cout << p.first.first << " -> " << p.second << "\n";
}

Hashing a template type

Here, I tried to make a map that its vertex can be user-defined class. But when I try to add template type element to the unordered_set it gives error. The code is:
#include <iostream>
#include <unordered_set>
#include <string>
#include <vector>
#include <functional>
template<class T> class Edge;
template<class T> class Vertex{ // Made it a class just for its constructor.
public:
template<class A> Vertex(A vert){
A vertex = vert;
std::unordered_set<Edge<A>> adjlist;
}
};
template<class T> class Edge{ // Made it a class just for its constructor.
public:
template<class A> Edge(Vertex<A> vert1, Vertex<A> vert2, int w){
Vertex<A> *origin = &vert1;
Vertex<A> *target = &vert2;
}
};
template<class T>
class WUG{
private:
std::unordered_set<Vertex<T>> vertices;
std::unordered_set<Edge<T>> edges;
int num_of_edges;
int num_of_vertices;
public:
WUG() {
num_of_edges = 0;
num_of_vertices = 0;
}
void addVertex(T newVert) {
Vertex<T> temp = Vertex<T>(newVert);
vertices.emplace(temp); //Problem is here
}
int main(int argc, char** argv) {
WUG<char> g1 = WUG<char>();
g1.addVertex('A');
g1.addVertex('B');
g1.addVertex('C');
return 0;
}
Error: it opens hashtable_policy.h and gives error at
template <typename _Key, typename _Hash>
struct __is_noexcept_hash : std::integral_constant<bool,
noexcept(declval<const _Hash&>()(declval<const _Key&>()))> //Here
{ };
[Error] no match for call to '(const std::hash<Vertex<char> >) (const Vertex<char>&)'
How do you emplace a template type object to unordered_set? How about pair of 2 template?
I believe you need to provide special hashing and comparison functions to make the hash set (or in my example's case, hash map) work. Here is a minimal example. Tested with C++11.
#include <unordered_map>
#include <iostream>
#include <algorithm>
template<typename T>
struct foo {
typedef T value_type;
foo(T x) : x(x) {}
T x;
};
template<typename T>
struct foo_hasher {
int operator()(const T &val) const {
return std::hash<typename T::value_type>()(val.x);
}
};
template<typename T>
struct foo_equality {
bool operator()(const T &left, const T& right) const {
return left.x == right.x;
}
};
int main() {
typedef std::unordered_map<foo<int>, int, foo_hasher<foo<int>>, foo_equality<foo<int>>> Map;
Map mp;
foo<int> x(5);
mp[x] = 10;
mp[foo<int>(10)] = 22;
std::for_each(mp.begin(), mp.end(), [](const Map::value_type &val) {
std::cout << val.first.x << ", " << val.second << "\n";
});
}
Note that both my hashing and equality function are not at all restrictive - they are wrt T rather than foo, but the principal should be the same.

Create a nested map in C++ [duplicate]

If I have definitions like:
typedef map<string, Foo> Foo_map_1
typedef map<string, Foo_map_1> Foo_map_2
typedef map<string, Foo_map_2> Foo_map_3
typedef map<string, Foo_map_3> Foo_map_4
typedef map<string, Foo_map_4> Foo_map_5
Is there anyway I can generalize that so I could do, for example,
Foo_map<10>
and have a 10-fold nested map. I don't need something like boost::recursive_wrapper because the number of levels is always constant.
This is seems easy enough even for the limited C++ metaprogramming power:
#include <map>
#include <string>
template<int N, typename K, typename V>
struct NMap { typedef std::map<K, typename NMap<N-1, K, V>::type> type; };
template<typename K, typename V>
struct NMap<1, K, V> { typedef std::map<K, V> type; };
int main(int argc, const char *argv[]) {
NMap<3, int, std::string>::type m;
m[1][2][3] = "Test";
return 0;
}
This works for me.
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct Foo
{
Foo() : _in(0) {}
Foo(int in) : _in(in) {}
int _in;
};
template <int N> struct Foo_map
{
map<string, Foo_map<N-1> > foo_Map;
Foo_map<N-1>& operator[](string const& key) { return foo_Map[key]; }
};
template <> struct Foo_map<1>
{
map<string, Foo> foo_Map;
Foo& operator[](string const& key) { return foo_Map[key]; }
};
int main()
{
Foo_map<1> map1;
map1["abcd"] = Foo(10);
Foo_map<2> map2;
map2["a"]["b"] = Foo(20);
Foo_map<10> map10;
map10["a"]["b"]["c"]["d"]["e"]["f"]["g"]["h"]["i"]["j"] = Foo(100);
std::cout << map1["abcd"]._in << std::endl;
std::cout << map2["a"]["b"]._in << std::endl;
std::cout << map10["a"]["b"]["c"]["d"]["e"]["f"]["g"]["h"]["i"]["j"]._in << std::endl;
}
The output of running the program:
10
20
100

Creating concept for member template function for use with boost::any in c++

I am trying to create a concept for use with boost::any. This concept should say that
a class has ha member function with signatur void templateFunction(T t). I have gotten this to compile and working fine, but only for one type at a time. Is what I am trying to do impossible?
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>
using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
class Foo
{
public:
template <class T>
void templateFunction(T t)
{
cout << t << endl;
}
};
template<class C, class T>
struct has_template_function
{
static void apply(C& cont, const T& arg) { cont.templateFunction(arg); }
};
namespace boost
{
namespace type_erasure
{
template<class C, class T, class Base>
struct concept_interface<has_template_function<C, T>, Base, C> : Base
{
void templateFunction(typename as_param<Base, const T&>::type arg)
{ call(has_template_function<C, T>(), *this, arg); }
};
}
}
int main()
{
any<has_template_function<_self, int>, _self&> c = Foo();
c.templateFunction(5);
//Compile error: cannot convert parameter 1 from 'const char [6]' to 'const int &'
//c.templateFunction("Hello");
return 0;
}
This is kind of possible by overloading, and documented in the official Boost.TypeErasure documentation.
The caveat is, as said in the comments:
You can't type-erase templates and keep their polymorphic nature
Therefore, you will have to specify the overloads explicitly in the requirements for your boost::typeerasure::any type.
You need to modify your concept interface as described in the docs, and add a string overload to the requirements section.
Your example, modified to handle overloads:
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/type_erasure/member.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/any.hpp>
#include <string>
#include <utility>
using namespace std;
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
struct FooStruct
{
template <class T>
void templateFunction(T t)
{
cout << t << endl;
}
};
template<class T, class U>
struct has_template_function
{
static void apply(T& t, const U& u) { t.templateFunction(u); }
};
namespace boost {
namespace type_erasure {
template<class T, class U, class Base, class Enable>
struct concept_interface< ::has_template_function<T, U>, Base, T, Enable> : Base
{
typedef void _fun_defined;
void templateFunction(typename as_param<Base, const U&>::type arg)
{
call(::has_template_function<T, U>(), *this, arg);
}
};
template<class T, class U, class Base>
struct concept_interface< ::has_template_function<T, U>, Base, T, typename Base::_fun_defined> : Base
{
using Base::templateFunction;
void templateFunction(typename as_param<Base, const U&>::type arg)
{
call(::has_template_function<T, U>(), *this, arg);
}
};
}
}
ostream& operator<<(ostream& os, const std::pair<int, string>& pair) {
os << "(" << pair.first << ", " << pair.second << ")";
return os;
}
int main()
{
any<
mpl::vector
<
has_template_function<_self, int>,
has_template_function<_self, std::string>,
has_template_function<_self, std::pair<int,std::string>>
>
, _self&> c = FooStruct();
c.templateFunction(5);
c.templateFunction("Hello");
c.templateFunction(std::make_pair(5, "Hello"));
return 0;
}

iterating getters of a vector of pointers

I am trying to write an iterator class which returns a getter function return value when it is dereferenced. The code works fine, my only problem is that I would like to write the member_ptr_functor using only one template parameter and not 3, since I am supposed to be able to deduce the types of the argument and return value from the member function type. I think the problematic one is the argument type, I tried using boost::remove_ptr&, but I couldn't compile it.
#include <iostream>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
using namespace boost;
using namespace std;
class CTest
{
private:
int m_x;
public:
CTest(int x) : m_x(x)
{
}
const int& GetX() const
{
return m_x;
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
class member_ptr_functor : public unary_function<ArgumentType, ResultType>
{
private:
MemFunType m_MemFun;
public:
typedef ArgumentType argument_type;
typedef ResultType result_type;
member_ptr_functor(MemFunType MemFun) : m_MemFun(MemFun)
{
}
result_type operator() (argument_type arg) const
{
return m_MemFun(&arg);
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
member_ptr_functor<MemFunType, ArgumentType, ResultType> make_member_ptr_functor(MemFunType MemFun)
{
return member_ptr_functor<MemFunType, ArgumentType, ResultType>(MemFun);
}
class CPrintFunctor : public unary_function<int, void>
{
public:
void operator() (const int n) const
{
cout << n << endl;
}
};
int main()
{
typedef vector<CTest> Container_t;
Container_t v;
v.push_back(CTest(1));
CPrintFunctor PF;
Container_t::const_iterator itStart = v.begin();
Container_t::const_iterator itEnd = v.end();
typedef member_ptr_functor<const_mem_fun_t<const int&, CTest> , CTest, const int&> member_ptr_functor_t;
member_ptr_functor_t MemberPtrFunctor = member_ptr_functor_t(mem_fun(&CTest::GetX));
typedef transform_iterator<member_ptr_functor_t, Container_t::const_iterator, const int&, const int> transform_iterator_t;
transform_iterator_t itTransformStart = make_transform_iterator(itStart, MemberPtrFunctor);
transform_iterator_t itTransformEnd = make_transform_iterator(itEnd, MemberPtrFunctor);
for_each(itTransformStart, itTransformEnd, PF);
return 0;
}
Hagai.
This does not answer your question directly but rather suggests alternative approach.
You are already using Boost, so why do you not take it one step further, use Boost.Range:
#include <boost/functional.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/transformed.hpp>
// ...
int main ()
{
// ...
boost::range::for_each (
boost::adaptors::transform (v, boost::mem_fun_ref (&CTest::GetX)),
PF);
}
This lets you write the functionality that you want without having to define own functors and without using too many typedefs.