// BOOST Includes
#include <boost/assign.hpp> // Boost::Assign
#include <boost/assign/list_of.hpp> // Boost::Assign::List_Of
#include <boost/assign/std/map.hpp> // Boost::Assign::Map_List_Of
#include <boost/tuple/tuple.hpp> // Boost::Tuples
// STD Includes
#include <map>
#include <vector>
#include <string>
// Using namespaces
using namespace std;
using namespace boost;
using namespace boost::assign;
// Consts
const map<string, string> query_map = map_list_of<string, string>
("4556_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 4556")
("7552_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 7552")
("234x_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 2344 OR PMU_ID = 2345 OR PMU_ID = 2346 OR PMU_ID = 2347 OR PMU_ID = 2348")
("813x_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 8132 OR PMU_ID = 8133 OR PMU_ID = 8134 OR PMU_ID = 8135 OR PMU_ID = 8136");
const map<string, std::vector<int>> vector_map = map_list_of<string, std::vector<int>>
("4556", list_of(4556))
("7552", list_of(7552))
("234x", list_of(2344)(2345)(2346)(2347)(2348))
("813x", list_of(8132)(8133)(8134)(8135)(8136));
Using boost - it's possible to init const std::containers for testing etc.
making a const std::map or std::map is pretty easy as the above code shows. Creating a const map<string, std::vector<int>> is a bit more complex - but still fairly easy.
I'm trying to come up with a const std::map<boost::tuples::tuple<string, string, string>, string> but I'm failing to initialize it. Has anyone else had any luck with it ?
// Typedefs
typedef boost::tuples::tuple<string, string, string> x3_string_tuple;
// Constants
const map<x3_string_tuple, string> query_selector_map = map_list_of<x3_string_tuple, string>
("4556", "SELECT", "FILENAME"), "4556_SELECT_FILENAME"); // ETC.
I tried this, and it fails because the keys of the map need to be comparable (with std::less, thus there needs to be an operator< defined). boost::tuple's comparison operators are defined in the header boost/tuple/tuple_comparison.hpp.
Having included that, this code works fine:
#include <boost/assign/list_of.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <map>
#include <string>
using std::string;
typedef boost::tuple<string, string, string> tpl_t;
int main() {
using boost::assign::map_list_of;
std::map<tpl_t, string> const m =
map_list_of(tpl_t("a","b","c"), "c")(tpl_t("x","y","c"), "z");
}
I would try
const map<x3_string_tuple, string> query_selector_map = map_list_of<x3_string_tuple, string>
(x3_string_tuple("4556", "SELECT", "FILENAME"), "4556_SELECT_FILENAME");
But, honestly, maybe it's easier just to have 3 separate lists of strings, and then one-by-one combine them into a tuple and add that to a map.
Related
This works in VS2018, but not in 2008, and i'm not sure how to fix it.
#include <map>
#include <string>
int main() {
std::map<std::string, std::string> myMap = {
{"Code", "Test"},
{"Code", "Test1"},
{"Code", "Test2"},
};
}
This is the error :
Error 2 error C2552: 'myMap' : non-aggregates cannot be initialized with initializer list
VS2008 is an old compiler that doesn't support C++11 which is needed for this.
You can insert each element:
int main() {
std::map<std::string, std::string> myMap;
myMap["Code"] = "Test";
myMap["Code"] = "Test1";
myMap["Code"] = "Test2";
}
Or you can use boost:
#include "boost/assign.hpp"
int main() {
std::map<std::string, std::string> myMap = boost::assign::map_list_of
("Code", "Test")
("Code", "Test1")
("Code", "Test2");
}
Option 1: Use a compiler that supports C++11 or a later version of the standard where extended list initialisation is well-formed. (I.e. give up on VS2008)
Option 2: Write the program in C++03 (or older if necessary) compliant dialect. An example:
typedef std::map<std::string, std::string> Map;
typedef Map::value_type Pair;
Pair elements[] = {
Pair("Code", "Test"),
Pair("Code", "Test1"),
Pair("Code", "Test2"),
};
const std::size_t length = sizeof(elements)/sizeof(*elements);
Map myMap(elements, elements + length);
To fix it you have to make it C++03 compliant (this is what vs2008 supports), so basically:
#include <map>
#include <string>
int main() {
std::map<std::string, std::string> myMap;
myMap["Code0"] = "Test0";
myMap["Code1"] = "Test1";
myMap["Code2"] = "Test2";
}
Boost.Assign can greatly simplify life:
#include <boost/assign.hpp>
#include <map>
#include <string>
int main()
{
::std::map< ::std::string, ::std::string > items;
::boost::assign::insert(items)
("Code", "Test")
("Code", "Test1")
("Code", "Test2");
}
How should I declare std::list(1) with iterators to std::map, which maps std::string to iterators of std::list (1) ? Is it possible?
std::list<std::map<std::string, (1) ???>::iterator>;
std::map<std::string, (1) ???::iterator>;
The reason I want this - FIFO queue with ability to fast remove by key.
One possible solution:
struct decl_t {
typedef std::map< std::string, decl_t > map_t;
typedef std::list< std::pair< int, typename map_t::iterator > > list_t;
list_t::iterator it;
};
For the purpose of a FIFO with the ability to remove by key, I suggest you use unordered_map, as you have no need for order in the map.
Following that, perhaps you could change your cross-referencing scheme. Use a list of strings, and a map mapping strings to iterators of such a list:
#include <unordered_map>
#include <list>
#include <string>
using map_t = unordered_map<string, list<string>::iterator>;
using list_t = list<string>;
For the direction of finding a key in the map once you have an iterator in the list, you need to perform a redundant hash on the name relative to your full iterator-to-iterator scheme, but it is still O(1) (expected). Conversely, your original scheme required logarithmic operations for removal by key, so you're probably still ahead.
To insert a new element, you could do something like this:
map_t map;
list_t list;
list.push_back("koko");
auto it = --list.end();
map["koko"] = it;
Example
#include <unordered_map>
#include <list>
#include <string>
using namespace std;
int main()
{
using map_t = unordered_map<string, list<string>::iterator>;
using list_t = list<string>;
map_t map;
list_t list;
list.push_back("koko");
auto it = --list.end();
map["koko"] = it;
}
Here is ugly, but complete example
#include <cassert>
#include <iostream>
#include <list>
#include <map>
#include <string>
struct decl_t {
typedef std::map<std::string, decl_t> map_t;
typedef std::list<std::pair<int, typename map_t::iterator>> list_t;
list_t::iterator it;
};
int main(int argc, const char* argv[])
{
decl_t::map_t map;
decl_t::list_t list;
auto list_it = list.emplace(list.end(), 42, decl_t::map_t::iterator());
const auto pair = std::make_pair(std::string("key"), decl_t{list_it});
auto result = map.insert(pair);
assert(result.second);
auto map_it = result.first;
list_it->second = map_it;
std::cout << list_it->second->first << std::endl;
std::cout << map_it->second.it->first << std::endl;
}
I had some help on a previous topic, where I had to change my map to use int in combination with strings. When I have done this it gives me a different issue. This is the issue:
src/main.cpp:11:29: error: no matching constructor for initialization of
'std::map<int, std::string>'
...tagMap {{"1", "data"}, {"2", "entry"}, {"3", "id"}, {"4", "content"}};
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It seems like the issue (which I looked up on another topic) seems to allude to the fact that the issue is to do with making your constructor take const references? I don't really understand how to implement this.
#include "pugi/pugixml.hpp"
#include <iostream>
#include <string>
#include <map>
int main()
{
pugi::xml_document doca, docb;
std::map<std::string, pugi::xml_node> mapa, mapb;
std::map<int, std::string> tagMap {{"1", "data"}, {"2", "entry"}, {"3", "id"}, {"4", "content"}};
if (!doca.load_file("a.xml") || !docb.load_file("b.xml")) {
std::cout << "Can't find input files";
return 1;
}
for (auto& node: doca.child(tagMap[1]).children(tagMap[2])) {
const char* id = node.child_value(tagMap[3]);
mapa[id] = node;
}
for (auto& node: docb.child(tagMap[1]).children(tagMap[2])) {
const char* idcs = node.child_value(tagMap[3]);
if (!mapa.erase(idcs)) {
mapb[idcs] = node;
}
}
}
Any help would be appreciated.
Try sth like:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
std::map<int, std::string> tagMap {make_pair(1, "data"), make_pair(2, "entry")};
}
Edit: The version without make_pair function is also valid:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
std::map<int, std::string> tagMap {{1, "data"}, {2, "entry"}};
}
The only thing you need to remember is that you shouldn't rely on compiler const string literal to number cast...
I'm new to C++ and have had some help with my program to compare two XML files. This is the code I have:
#include "pugixml.hpp"
#include <iostream>
#include <unordered_map>
int main() {
pugi::xml_document doca, docb;
std::map<string, pugi::xml_node> mapa, mapb;
if (!doca.load_file("a.xml") || !docb.load_file("b.xml"))
return 1;
for (auto& node: doca.child("site_entries").children("entry")) {
const char* id = node.child_value("id");
mapa[new std::string(id, strlen(id))] = node;
}
for (auto& node: docb.child("site_entries").children("entry"))
const char* idcs = node.child_value("id");
std::string id = new std::string(idcs, strlen(idcs));
if (!mapa.erase(id)) {
mapb[id] = node;
}
}
}
I seem to get a lot of errors when I try and compile it.
The first one I get is this:
src/main.cpp:10:14: error: unknown type name 'string'; did you mean 'std::string'?
std::map<string, pugi::xml_node> mapa, mapb;
~~~~~^~~
From what I understand, I have specified it correctly. Should I change it as it requests or is something else a-miss?
You need to include the string library in order to use std::string.
Since you mentioned a lot of errors, I suspect you forgot to include <cstring> in order to use strlen().
#include <string>
#include <cstring>
You have to include the string library:
#include <string>
Use the following way:
std::string varName = "var value";
I'm using Clion IDE and it worked for me.
So in my cpp file I'm trying to declare a map as follows:
map<string, vector<myStruct>> myMap;
At the top of my file I have written using namespace std and I also have #include <string>
.
However I'm getting these weird errors:
error: ISO C++ forbids declaration of ‘map’ with no type
I don't know how to fix it. If I write #include <map> that just causes the compiler to freak out.
do you have #include <map>? rest looks valid,
however you might need to add a space if your C++ standard is not C++11:
#include <map>
#include <vector>
#include <string>
using namespace std;
map<string, vector<myStruct> > myMap;
^^^
even better not use namespace std:
#include <map>
#include <vector>
#include <string>
std::map<std::string, std::vector<myStruct> > myMap;
You need to include map header file.
#include <map>
Meanwhile, in case you are not using C++11, you need a space:
map<string, vector<myStruct> > myMap;
//^^
You should also include <map>. std::map is introduced through this header.
Furthermore, using namespace std is considered a bad practice. You should either have a using statement or use the prefix the name with std:: to denote a fully-qualified identifier:
#include <map>
#include <string>
#include <vector>
std::map<std::string, std::vector<myStruct>> myMap;
Note, the lack of a using statement ;)
#include <vector>
#include <string>
#include <map>
#include <iostream>
typedef int myStruct;
std::map<std::string, std::vector<myStruct>> myMap;
int
main()
{
std::vector<myStruct> testMe = { 1, 2, 3};
myMap["myTest"] = testMe;
std::cout << myMap.size() << std::endl;
return(0);
}