How to get the value out of a multi index - c++

I am trying to do one multi map(4 variables) using boost- multi index. Can I know how to get the value of a particular index like
tmp_Container.get<name>().find("aaa")->firstVariable
EDIT
struct EnumStruct
{
int microsoftEnum;
std::string microsoftEnumString;
int localEnum;
std::string localEnumString;
}
typedef bmi::multi_index_container<
EnumStruct,
bmi::ordered_unique<bmi::tag<localEnum>,bmi::member <
EnumStruct,std::string,&EnumStruct::localEnumString > >
>
> boost_Enum_Container;
boost_Enum_Container enumStructContainer;
int main()
{
enumStructContainer.insert(EnumStruct(1,"MS_1",11,"LOC11"));
enumStructContainer.insert(EnumStruct(2,"MS_2",22,"LOC22"));
enumStructContainer.insert(EnumStruct(3,"MS_3",33,"LOC33"));
//enumStructContainer.get<0>().find(1);
//boost_Enum_Container::index<localEnum>::type&
localEnum_Index=enumStructContainer.get<localEnum>().find(22)->firstVariable;
boost_Enum_Container::iterator
return 0;
}

You need the project function. See http://www.boost.org/doc/libs/1_39_0/libs/multi_index/doc/tutorial/basics.html#projection and http://www.boost.org/doc/libs/1_46_0/libs/multi_index/doc/reference/multi_index_container.html#projection. Thus: tmp_Container.project<0>(tmp_Container.get<name>.find("aaa")).

You are using boost::multi_index::tag in a wrong way. To use it, you must provide a valid struct.
Also you are trying to search a number in a string index. Below code must work, I did not test it though.
struct LOCALENUM { };
struct LOCALENUMSTR { };
using namespace boost::multi_index;
typedef boost::multi_index_container<
EnumStruct,
indexed_by<
ordered_unique<tag<LOCALENUM>,member<EnumStruct,int,&EnumStruct::localEnum > >
>,
ordered_unique<tag<LOCALENUMSTR>,member<EnumStruct,std::string,&EnumStruct::localEnumString > >
>
>
> boost_Enum_Container;
typedef boost_Enum_Container::index<LOCALENUM>::type::iterator EnumIterator;
typedef boost_Enum_Container::index<LOCALENUMSTR>::type::iterator EnumStrIterator;
EnumIterator enumiter = enumStructContainer.get<LOCALENUM>().find(22);
EnumStruct & enum_struct = (*eniter);
// There you go :
std::cout << enum_struct.microsoftEnumString << "\n";
//Searching for LocalEnumString :
EnumStrIterator enunstriter = enumStructContainer.get<LOCALENUMSTR>().find("LOC22");
EnumStruct & enum_struct = (*enunstriter );
std::cout << enum_struct.microsoftEnumString << "\n";

As has been mentioned multiple times in your other recent questions, the ordered_unique index specifier has the same interface as std::map; so if you know how to use std::map (hint, hint) then this should be very straightforward:
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
struct EnumStruct
{
EnumStruct(int const me, std::string const& mes, int const le, std::string const& les)
: microsoftEnum(me),
microsoftEnumString(mes),
localEnum(le),
localEnumString(les)
{ }
int microsoftEnum;
std::string microsoftEnumString;
int localEnum;
std::string localEnumString;
};
namespace bmi = boost::multi_index;
struct localEnum_t;
typedef bmi::multi_index_container<
EnumStruct,
bmi::indexed_by<
bmi::ordered_unique<
bmi::tag<localEnum_t>,
bmi::member<EnumStruct, int, &EnumStruct::localEnum>
>
>
> boost_Enum_Container;
int main()
{
boost_Enum_Container enumStructContainer;
enumStructContainer.insert(EnumStruct(1, "MS_1", 11, "LOC11"));
enumStructContainer.insert(EnumStruct(2, "MS_2", 22, "LOC22"));
enumStructContainer.insert(EnumStruct(3, "MS_3", 33, "LOC33"));
boost_Enum_Container::index_iterator<localEnum_t>::type iter = enumStructContainer.get<localEnum_t>().find(22);
if (iter != enumStructContainer.get<localEnum_t>().end())
std::cout << "found, localEnumString == " << iter->localEnumString << std::endl;
else
std::cout << "didn't find anything" << std::endl;
}

Related

how to use the PEGTL parser with a separate lexer?

I have already a lexer and want to use my own token types as the input for a PEGTL parser. As an example, here is a modified version of the sum example, which reads from stdin:
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <tao/pegtl.hpp>
using namespace TAO_PEGTL_NAMESPACE;
namespace sum
{
struct num : seq< plus< digit > > {};
struct int_list
: list< num, one< ',' > >
{};
struct grammar
: seq< int_list, eof >
{};
template< typename Rule >
struct action
{};
template<>
struct action< num >
{
template< typename ActionInput >
static void apply( const ActionInput& in, int& sum )
{
sum += atoi(in.string().c_str());
}
};
} // namespace sum
struct Token {
typedef enum { COMMA, NUM, END_OF_FILE } Type;
Token(Type type, int num = 0) : type(type), num(num) {}
Type type;
int num;
};
int main()
{
// this works, can be called like this:
// echo -n "1,2,3" | ./a.out
int d = 0.0;
if( parse< sum::grammar, sum::action >( istream_input(std::cin, 16, "stdin"), d )) {
std::cout << "parsing OK; sum = " << d << std::endl;
}
else {
std::cout << "parsing failed" << std::endl;
}
// how can I do this when I have already the tokens in a vector?
std::vector<Token> tokens;
tokens.push_back(Token(Token::Type::NUM, 1));
tokens.push_back(Token(Token::Type::COMMA));
tokens.push_back(Token(Token::Type::NUM, 2));
tokens.push_back(Token(Token::Type::COMMA));
tokens.push_back(Token(Token::Type::NUM, 3));
tokens.push_back(Token(Token::Type::END_OF_FILE));
}
It can be compiled like this: g++ -std=c++17 -I PEGTL/include parser.cc. The files in PEGTL/include are from the PEGTL repository.
How do I need to modify the parser so that the vector of tokens are used instead of std::cin? I think I have to write my own ParseInput struct, but I couldn't define all required methods and types for it. And how can I use then the token objects in the parser for this sum example?

I need help while inserting in a map of integer and set of a structure

The code is :
#include <map>
#include <utility>
typedef struct
{
int d_number;
int o_number;
} d_o_pair;
std::set<d_o_pair> d_o_set;
std::map<int, d_o_set> my_map;
}
i want to insert into the map. but i am not able to
. i was using like this : this->my_map[5].insert(make_pair(0, 2)). the compiler throws me error telling no function matches call to insert
Following sample code tell us inserting into map. For inserting to set, you need to overload the '<' operator to define the ordering condition in the structure with a constructor and insert in a similar fashion using insert function.
#include<iostream>
#include<map>
using namespace std;
typedef struct
{
int d_number;
int o_number;
}d_o_number;
int main()
{
d_o_number s1;
s1.d_number = 100;
s1.o_number = 1000;
std::map<int, d_o_number> d_o_map;
d_o_map.insert(std::pair<int, d_o_number>(0, s1));
// showing contents:
std::map<int,d_o_number>::iterator it = d_o_map.begin();
std::cout << "d_o_map contains:\n";
for (it=d_o_map.begin(); it!=d_o_map.end(); ++it)
std::cout << it->first << " => " << it->second.d_number<<","<<it->second.o_number << '\n';
return 0;
}
Try the following
#include <map>
#include <set>
#include <utility>
typedef std::pair<int, int> d_o_pair;
typedef std::set<d_o_pair> d_o_set;
int main()
{
std::map<int, d_o_set> my_map;
my_map[5].insert( std::make_pair( 0, 2 ) );
}
Or the following
#include <map>
#include <set>
#include <utility>
typedef struct d_o_pair
{
int d_number;
int o_number;
bool operator <( const d_o_pair &rhs ) const
{
return d_number < rhs.d_number || ( !( rhs.d_number < d_number ) && ( o_number < rhs.o_number ) );
}
} d_o_pair;
typedef std::set<d_o_pair> d_o_set;
int main()
{
std::map<int, d_o_set> my_map;
my_map[5].insert( { 0, 2 } );
}

Hash an arbitrary precision value (boost::multiprecision::cpp_int)

I need to get the hash of a value with arbitrary precision (from Boost.Multiprecision); I use the cpp_int backend. I came up with the following code:
boost::multiprecision::cpp_int x0 = 1;
const auto seed = std::hash<std::string>{}(x0.str());
I don't need the code to be as fast as possible, but I find it very clumsy to hash the string representation.
So my question is twofold:
Keeping the arbitrary precision, can I hash the value more efficiently?
Maybe I should not insisting on keeping the arbitrary precision and I should convert to a double which I could hash easily (I would still however make the comparison needed for the hash table using the arbitrary precision value)?
You can (ab)use the serialization support:
Support for serialization comes in two forms:
Classes number, debug_adaptor, logged_adaptor and rational_adaptor have "pass through" serialization support which requires the underlying backend to be serializable.
Backends cpp_int, cpp_bin_float, cpp_dec_float and float128 have full support for Boost.Serialization.
So, let me cobble something together that works with boost and std unordered containers:
template <typename Map>
void test(Map const& map) {
std::cout << "\n" << __PRETTY_FUNCTION__ << "\n";
for(auto& p : map)
std::cout << p.second << "\t" << p.first << "\n";
}
int main() {
using boost::multiprecision::cpp_int;
test(std::unordered_map<cpp_int, std::string> {
{ cpp_int(1) << 111, "one" },
{ cpp_int(2) << 222, "two" },
{ cpp_int(3) << 333, "three" },
});
test(boost::unordered_map<cpp_int, std::string> {
{ cpp_int(1) << 111, "one" },
{ cpp_int(2) << 222, "two" },
{ cpp_int(3) << 333, "three" },
});
}
Let's forward the relevant hash<> implementations to our own hash_impl specialization that uses Multiprecision and Serialization:
namespace std {
template <typename backend>
struct hash<boost::multiprecision::number<backend> >
: mp_hashing::hash_impl<boost::multiprecision::number<backend> >
{};
}
namespace boost {
template <typename backend>
struct hash<multiprecision::number<backend> >
: mp_hashing::hash_impl<multiprecision::number<backend> >
{};
}
Now, of course, this begs the question, how is hash_impl implemented?
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;
}
};
This looks pretty simple. That's because Boost is awesome, and writing a hash_sink device for use with Boost Iostreams is just the following straightforward exercise:
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;
};
Full Demo:
Live On Coliru
#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> >
{};
}
namespace boost {
template <typename backend>
struct hash<multiprecision::number<backend> >
: mp_hashing::hash_impl<multiprecision::number<backend> >
{};
}
template <typename Map>
void test(Map const& map) {
std::cout << "\n" << __PRETTY_FUNCTION__ << "\n";
for(auto& p : map)
std::cout << p.second << "\t" << p.first << "\n";
}
int main() {
using boost::multiprecision::cpp_int;
test(std::unordered_map<cpp_int, std::string> {
{ cpp_int(1) << 111, "one" },
{ cpp_int(2) << 222, "two" },
{ cpp_int(3) << 333, "three" },
});
test(boost::unordered_map<cpp_int, std::string> {
{ cpp_int(1) << 111, "one" },
{ cpp_int(2) << 222, "two" },
{ cpp_int(3) << 333, "three" },
});
}
Prints
void test(const Map&) [with Map = std::unordered_map<boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, std::basic_string<char> >]
one 2596148429267413814265248164610048
three 52494017394792286184940053450822912768476066341437098474218494553838871980785022157364316248553291776
two 13479973333575319897333507543509815336818572211270286240551805124608
void test(const Map&) [with Map = boost::unordered::unordered_map<boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<> >, std::basic_string<char> >]
three 52494017394792286184940053450822912768476066341437098474218494553838871980785022157364316248553291776
two 13479973333575319897333507543509815336818572211270286240551805124608
one 2596148429267413814265248164610048
As you can see, the difference in implementation between Boost's and the standard library's unordered_map show up in the different orderings for identical hashes.
Just to say that I've just added native hashing support (for Boost.Hash and std::hash) to git develop. It works for all the number types including those from GMP etc. Unfortunately that code won't be released until Boost-1.62 now.
The answer above that (ab)uses serialization support, is actually extremely cool and really rather clever ;) However, it wouldn't work if you wanted to use a vector-based hasher like CityHash, I added an example of using that by accessing the limbs directly to the docs: https://htmlpreview.github.io/?https://github.com/boostorg/multiprecision/blob/develop/doc/html/boost_multiprecision/tut/hash.html Either direct limb-access or the serialization tip will work with all previous releases of course.

boost::multi_index_container: Take equal_range from arbitrary index, implement loop only once

I have a multi_index_container that looks basically like this:
struct MyStruct {
int a, b, c;
};
struct Tag1;
struct Tag2;
typedef multi_index_container<
MyStruct,
indexed_by<
hashed_non_unique<
tag<Tag1>,
composite_key<
MyStruct,
member<MyStruct, int, &MyStruct::a>,
member<MyStruct, int, &MyStruct::b>
>
>,
hashed_non_unique<
tag<Tag2>,
composite_key<
MyStruct,
member<MyStruct, int, &MyStruct::a>,
member<MyStruct, int, &MyStruct::b>,
member<MyStruct, int, &MyStruct::c>
>
>
>
> MyContainer;
I instantiate such a container and use its indices like so:
MyContainer c;
MyContainer::index<Tag1>::type& index1 = c.get<Tag1>;
MyContainer::index<Tag2>::type& index2 = c.get<Tag2>;
Now, at runtime, I want to do an equal_range on one of the two indices. Which index is actually used, is dependent on the current configuration. What I'm trying to accomplish is something like this:
// Search in container
SomeType range;
if (useIndex1)
range = index1.equal_range(...);
else
range = index2.equal_range(...);
// Loop through range
for (auto i = range.first; i != range.second; ++i)
...
I don't know how to do this. As it turns out, the return type of index1.equal_range is a pair of iterators that are different from those returned by index2.equal_range. Is there a common base type to the two? Looking at my example, what would SomeType have to look like? I don't want to repeat the for loop in my code for every index that may possibly be used.
Instead of trying to do type erasure with range, put your loop logic into a lambda and apply it using std::for_each:
#include <boost\multi_index_container.hpp>
#include <boost\multi_index\composite_key.hpp>
#include <boost\multi_index\member.hpp>
#include <boost\multi_index\hashed_index.hpp>
using namespace boost::multi_index;
struct MyStruct {
int a, b, c;
};
struct Tag1;
struct Tag2;
typedef multi_index_container
<
MyStruct
, indexed_by
<
hashed_non_unique
<
tag<Tag1>
, composite_key
<
MyStruct
, member<MyStruct, int, &MyStruct::a>
, member<MyStruct, int, &MyStruct::b>
>
>
, hashed_non_unique
<
tag<Tag2>
, composite_key
<
MyStruct
, member<MyStruct, int, &MyStruct::a>
, member<MyStruct, int, &MyStruct::b>
, member<MyStruct, int, &MyStruct::c>
>
>
>
> MyContainer;
int main()
{
MyContainer c;
MyContainer::index<Tag1>::type& index1 = c.get<Tag1>();
MyContainer::index<Tag2>::type& index2 = c.get<Tag2>();
//! Add some values
for (int i = 0; i < 10; ++i)
{
MyStruct s = { i, i * 2, i * 3 };
c.insert(s);
}
auto loop = [](const MyStruct& s){ std::cout << "{ " << s.a << ", " << s.b << ", " << s.c << " }" << std::endl; };
// Search in container
bool useIndex1 = true;
if (useIndex1)
{
auto range = std::make_pair(index1.begin(), index1.end());
std::for_each(range.first, range.second, loop);
}
else
{
auto range = std::make_pair(index1.begin(), index1.end());
std::for_each(range.first, range.second, loop);
}
// Loop through range
//for (auto i = range.first; i != range.second; ++i)
return 0;
}

how can I store 3 integer in priority_queue?

I want to store 3 integer in priority_queue. I know how to store 2 integer.
I store 2 integer with pair<int,int>
my code
priority_queue<pair<int,int> , vector<pair<int,int> > , greater<pair<int,int> > > pq;
pq.push(make_pair(5,6));
but I don't know how can I store 3 integer. I need help.
sorry for my English.
Simplest would be create a struct which logically binds all the integers and create a priority queue of that struct objects.
EDIT
Sample code:
#include <queue>
using namespace std;
struct S
{
int m_n1;
int m_n2;
int m_n3;
S(int n1, int n2, int n3) : m_n1(n1), m_n2(n2), m_n3(n3)
{
}
bool operator<(const struct S& other) const
{
//Your priority logic goes here
return m_n1 < other.m_n1;
}
};
int main()
{
priority_queue<S> pq;
//Add the elements to the queue
pq.push(S(1,2,3));
pq.push(S(4,2,3));
pq.push(S(2,2,3));
//This element will be S(4,2,3)
S s1 = pq.top();
pq.pop();
return 0;
}
or the easy way: std::pair<int,std::pair<int,int>>
You may use Boost::Tuple
#include "boost/tuple/tuple.hpp"
#include <queue>
#include <vector>
#include <iostream>
typedef boost::tuple<int, int, int> triple_t;
class my_greater {
public:
bool operator() (const triple_t& arg1, const triple_t& arg2) const
{
return arg1.get<0>() > arg2.get<0>();
return false;
}
};
typedef std::priority_queue<triple_t, std::vector<triple_t>, my_greater>
my_priority_queue;
int main()
{
my_priority_queue triples;
triples.push(boost::make_tuple(1,2,3));
triples.push(boost::make_tuple(10,20,30));
triples.push(boost::make_tuple(5,10,15));
triples.push(boost::make_tuple(15,30,45));
triples.push(boost::make_tuple(2,4,6));
std::cout << "Result: \n";
while (!triples.empty())
{
const triple_t& t = triples.top();
std::cout << t.get<0>() << ", " << t.get<1>() << ", " << t.get<2>() << std::endl;
triples.pop();
}
return 0;
}