I am playing with c++ code today. Learning about std containers. I'm trying to insert and update data in a std::map but for some reason I can't insert values into a map. Keys will insert but not values. The code at the bottom will print the following if you enter something into the terminal that opens. In this example I entered "test". Anyway, my questions are, why is the insert returning false, why in the value not inserting?
test
first
failed
Context1 :
Here is the code:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <map>
#include <random>
static std::map<std::string, std::string> currentFullState;
static const std::string sDEFAULT_STRING = "";
void PringCurrentState()
{
std::map<std::string, std::string>::iterator stateData = currentFullState.begin();
while (stateData != currentFullState.end())
{
std::cout << stateData->first << " : ";
std::cout << stateData->second << std::endl;
stateData++;
};
}
void UpdateState(std::string context, std::string data)
{
if (currentFullState[context] == sDEFAULT_STRING)
{
// first entry, possibly special?
std::cout << "first" << std::endl;
auto result = currentFullState.insert(std::make_pair(context, data.c_str()));
if (result.second == false)
std::cout << "failed" << std::endl;
else
std::cout << "good" << std::endl;
}
else if (data != currentFullState[context])
{
// change in value
}
else
{
currentFullState[context] == data;
}
}
void DoWork()
{
if (rand() % 2)
{
UpdateState("Context1", "Data1");
}
else
{
UpdateState("Context2", "Data2");
}
}
int main()
{
std::string command = "";
for (;;)
{
PringCurrentState();
std::cin >> command;
DoWork();
if (command == "q")
{
break;
}
}
return 0;
}
Why does the insert not work?
Certainly would help if you wrote
currentFullState[context] = data;
instead of
currentFullState[context] == data;
Also
auto result = currentFullState.insert(std::make_pair(context, data));
should be preferred to
auto result = currentFullState.insert(std::make_pair(context, data.c_str()));
Slightly surprised that the second one compiles.
=========================================================================
The real reason the insert fails is that you are adding that key for the second time. This is the first time
if (currentFullState[context] == sDEFAULT_STRING)
operator[] on a map always adds the key to the map. This is why your second attempt to add with
auto result = currentFullState.insert(std::make_pair(context, data.c_str()));
fails, the key is already present. If you had written
currentFullState[context] = data;
Then it would work.
Related
I'm learnig C++. Here is my problem: I'm trying to read data from a text file and save it to a map<string, struct> and then have it print out all the keys from the map preferably in alphabetical order. The data has 2 strigns and a float. I can't get this to print even after having tried many different solutions.
Heres what I've got so far:
Here is my struct:
struct category
{
std::string tram_stop;
float dist;
};
using Tram = std::map<std::string, std::vector<category>>;
Here is where I try to save the data to the map.
void store(Tram& tram, std::vector<std::string>& tram_data)
{
if (tram.find (tram_data.at (0)) == tram.end ())
{
tram[tram_data.at (0)] = {};
}
else
{
tram.at (tram_data.at (0)).push_back (category {tram_data.at (1), std::stof(tram_data.at(2))});
}
}
And here is main().
int main()
{
Tram tram;
print_rasse();
// Ask input filename.
std::string filename;
std::cout << "Give a name for input file: ";
std::cin >> filename;
// Read input file.
std::ifstream file_in;
file_in.open (filename);
if (!file_in.is_open ())
{
std::cout << INVALID_FILE << std::endl;
return EXIT_FAILURE;
}
std::vector<std::string> tram_data;
if (file_in.is_open())
{
std::string line;
while( std::getline(file_in,line) )
{
std::stringstream ss(line);
std::string tram_line, tram_stop, distance;
std::getline(ss,tram_line,';'); //std::cout<< ""<<tram_line <<" ";
std::getline(ss,tram_stop,';'); //std::cout<<" "<<tram_stop<<" ";
std::getline(ss,distance); //std::cout<<" "<<distance<< " ";
if (tram_line != "" && tram_stop != "")
{
tram_data.push_back (tram_line);
tram_data.push_back (tram_stop);
tram_data.push_back (distance);
//std::cout << tram_line << " " << distance << std::endl;
}
else
{
std::cout << INVALID_FORMAT << std::endl;
return EXIT_FAILURE;
}
}
file_in.close ();
store(tram, tram_data);
}
This is the part I think doesn't work. Tried different iterators too.
if (upper_com == "LINES")
{
std::cout << "All tramlines in alphabetical order:" << std::endl;
for (auto& item : tram)
{
std::cout << item.first << std::endl;
}
}
Your implementation of store will create a vector for the first item added for a particular tram_data[0] value, but will not add anything to the vector. This results in losing that first item, and can result in no output because of the empty vectors.
That function can be simplified:
void store(Tram& tram, std::vector<std::string>& tram_data)
{
if (tram_data.size() < 3) throw std::out_of_range();
tram[tram_data[0]].emplace_back(tram_data[1], std::stof(tram_data[2]));
}
You don't need to use at with tram because you want to create the entry if it doesn't exist. at with tram_data will result in an exception being thrown if there are fewer than three elements in tram_data, so that check has been moved outside all the accesses to the vector.
I've written a code which creates a list of buses that you can modify and manage. The whole managing process is proceed by writing strings in console. After running code I'm receiving 3 errors, none of which I understand therefore can fix. Code is planned this way:
NEW_BUS - Adds new bus in list by taking it's number, amount of stops and stop list.
ALL_BUSES - Display all buses in lexicographical order (by their name)
STOPS_FOR_BUS - Display all stops specific bus follows.
BUSES_FOR_STOP - Diplay all buses that go though the specific stop.
Here are error list:
1. operator _surrogate_func: no matching overload found
2. Failed to specialize function template 'unknown-type std::less::operator ()(_Ty 1 &&,_Ty2 &&)
3. illegal expression
All errors come from line 617 from xutility file.
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <tuple>
#include <iterator>
using namespace std;
class Bus {
public:
int StopsAmount;
string BusNumber;
vector<string> Stops;
Bus(tuple<string, int, vector<string>> BusParams) {
BusNumber = get<0>(BusParams);
StopsAmount = get<1>(BusParams);
Stops = get<2>(BusParams);
}
void ShowStops() {
cout << BusNumber << ": ";
for (int i = 0; i < StopsAmount; i++) cout << Stops[i] << " ";
cout << "\n";
}
bool FindStop(string Stop) {
for (int i = 0; i < StopsAmount; i++) {
if (Stops[i] == Stop) {
return true;
}
}
return false;
}
};
class BusTraffic {
public:
BusTraffic() {
while (true) {
string Request;
cin >> Request;
switch (Request[0]) {
case 'N': NEW_BUS(Request.substr(8, Request.length() - 8)) ;
break;
case 'B': BUSES_FOR_STOP(Request.substr(15, Request.length() - 15));
break;
case 'S': STOPS_FOR_BUS(Request.substr(14, Request.length() - 14));
break;
case 'A': ALL_BUSES();
break;
}
}
}
private:
list<Bus> BusList;
void NEW_BUS(string Request) {
BusList.push_back(Bus::Bus(SplitString(Request)));
}
void BUSES_FOR_STOP(string Stop) {
cout << Stop << ": ";
for (list<Bus>::iterator It = BusList.begin(); It != BusList.end(); It++) {
if (It->FindStop(Stop)) {
cout << It->BusNumber << " ";
}
}
cout << endl;
}
void STOPS_FOR_BUS(string Name) {
cout << Name << ": ";
for (list<Bus>::iterator It = BusList.begin(); It != BusList.end(); It++) {
if (It->BusNumber == Name) {
It->ShowStops();
}
}
}
void ALL_BUSES() {
if (BusList.size() > 0) {
BusList.sort();
for (list<Bus>::iterator It = BusList.begin(); It != BusList.end(); It++) {
cout << It->BusNumber << ": ";
It->ShowStops();
}
}
else {
cout << "No buses" << endl;
}
}
// Converting string to information about bus
tuple<string, int, vector<string>> &SplitString(string str) {
tuple<string, int, vector<string>> BusParams;
string Word = "";
int WordNum = 0;
for (auto Letter : str) {
if (Letter == ' ') {
if (WordNum == 0) get<0>(BusParams) = Word;
if (WordNum == 1) get<1>(BusParams) = stoi(Word);
if (WordNum == 2) get<2>(BusParams).push_back(Word);
Word = "";
WordNum++;
}
else {
Word = Word + Letter;
}
}
get<2>(BusParams).push_back(Word);
return BusParams;
}
};
int main() {
BusTraffic TestTraffic;
return 0;
}
Unfortunately, you are absolutely correct. the error message here is just terrible. It's just from experience that you learn to interpret that as a missing less-than-operator.
So something in the lines of:
bool operator< (const Bus& lhs, const Bus& rhs) {
// however you want to sort them...
return (lhs.BusNumber < rhs.BusNumber);
}
The other small bug is within NEW_BUS: In C++ you don't need to specify the constructor name. So it's not Bus::Bus it's just Bus
Last but not least your SplitString is returning a reference to a local variable. In general that's a bad idea as that memory might simply not be accessible anymore when you try to. Just remove "&" from the return type. Further explanations.
You're trying to sort a list of buses. By the sounds of it there is no overload for the less than operator. This means C++ doesn't know how to compare objects of type bus. Add this to your Bus class and it should work. This overload of the less than operator returns true if the other bus is less than the current bus.
bool operator < (const Bus& otherBus) const {
if(otherBus.StopsAmount < this.StopsAmount) {
return true;
}
return false;
}
Useful links with more details:
http://fusharblog.com/3-ways-to-define-comparison-functions-in-cpp/
https://www.tutorialspoint.com/cplusplus/relational_operators_overloading.htm
I'm new to c++ after learning basic Object Oriented Programming in Java so I'm having a difficult time grasping memory deallocation. The assignment was to create a Weighted Directed Graph...
I'm getting the error: "terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc" when I run certain inputs through my code, and I'm having a difficult time figuring out what is causing it.
I googled the error and found that it was a memory problem, so I attempted to go through my code and try to find any leaks, but I am not sure where they are. Most posts are talking about pointers, which I do not tend to implement because I am unfamiliar with them. Thank you for your time!
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <iterator>
#include <map>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
class WDGraph {
private:
map<string,map<string,int>> edges;
vector<string> verts;
list<string> leaves;
list<string> roots;
list<string> selfEdges;
public:
list<string> getRoots() { return roots; }
list<string> getLeaves() { return leaves; }
void addVert(string key) {
verts.push_back(key);
}
void link(string start, string dest, int cost) {
edges[start].insert(make_pair(dest,cost));
if (!containsLeaf(dest) && !containsVert(dest))
leaves.push_back(dest);
if (!containsRoot(start) && !containsVert(start))
roots.push_back(start);
if (start == dest)
selfEdges.push_back(start);
roots.remove(dest);
leaves.remove(start);
}
bool containsVert(string key) {
for (int i=0; i < verts.size(); i++) {
if (key == verts[i]) {
return true;
}
}
return false;
}
bool containsRoot(string key) {
bool found = (find(roots.begin(), roots.end(), key) != roots.end());
return found;
}
bool containsLeaf(string key) {
bool found = (find(leaves.begin(), leaves.end(), key) != leaves.end());
return found;
}
WDGraph() { }
void printWDG() {
cout << "Printing Weighted Directed Graph." << endl;
for (auto itr1 = edges.begin(); itr1 != edges.end(); ++itr1) {
for (auto itr2 = itr1->second.begin(); itr2 != itr1->second.end(); ++itr2) {
if (itr2->first == "null" && containsRoot(itr1->first)) {
cout << "[" << itr1->first << "]";
}
else if (itr2->first != "null")
cout << "[" << itr1->first << " -> ";
cout << itr2->first << ", " << itr2->second << "] ";
}
cout << "" << endl;
}
}
void printNumVerts() {
cout << "Total number of vertices: " << verts.size() << endl;
}
void printRoots() {
int num_roots = 0;
cout << "Vertices with zero inbound edges: " << endl;
for (auto itr = roots.begin(); itr != roots.end(); ++itr) {
cout << "[" << *itr << "]" << endl;
num_roots++;
}
if (num_roots == 0) cout << "None" << endl;
}
void printLeaves() {
int num_leaves = 0;
cout << "Vertices with zero outbound edges:" << endl;
for (auto itr = leaves.begin(); itr != leaves.end(); ++itr) {
if (*itr != "null")
cout << "[" << *itr << "]" << endl;
num_leaves++;
}
if (num_leaves == 0) cout << "None" << endl;
}
void printSelfEdges() {
cout << "Vertices with self edges:" << endl;
for (auto itr = selfEdges.begin(); itr != selfEdges.end(); ++itr) {
cout << "[" << *itr << "]" << endl;
}
}
};
int main() {
WDGraph myWDG;
string filePath;
string line;
int weight;
size_t commaPos;
vector<string> sVector;
ifstream dataFile;
// cout << "Please enter the relative path to an input file." << endl;
// getline (cin, filePath);
// cout << "The file path you entered was " << filePath << endl;
// dataFile.open(filePath);
dataFile.open("input.csv"); //test input
while (getline (dataFile, line)) {
commaPos = line.find(',');
//Parse input file into string vector
while (line.length() >= 1) {
if (line.length() == 1) {
sVector.push_back(line);
break;
}
sVector.push_back(line.substr(0,commaPos));
line = line.substr(commaPos+1);
commaPos = line.find(',');
}
//Create vertices depending on number of parameters
if (sVector.size() == 1) {
if (!myWDG.containsVert(sVector[0])) {
myWDG.addVert(sVector[0]);\
}
myWDG.link(sVector[0], "null", 0);
}
if (sVector.size() == 3) {
if (!myWDG.containsVert(sVector[0])) {
myWDG.addVert(sVector[0]);
}
if (!myWDG.containsVert(sVector[1])) {
myWDG.addVert(sVector[1]);
}
weight = stoi(sVector[2]);
myWDG.link(sVector[0], sVector[1], weight);
}
sVector.clear();
}
myWDG.printWDG();
myWDG.printNumVerts();
myWDG.printRoots();
myWDG.printLeaves();
myWDG.printSelfEdges();
}
When my .csv has simple stuff it works as expected, for example:
a,b,1
c,d,2
e
f,f,3
However, if I have stuff like this I get the error "terminate called after throwing an instance of 'std::bad_alloc':
Hello
World,Hello,3
My,Name,4
Is
Nikki,Hello,3
As mentioned by Z E Nir, your line parsing code fails to consume any input if there is no comma "," in the line. You can of course debug your line parsing code, as debugging is a valuable skill to develop anyway.
However, a possible alternative to debugging consists in finding an existing C++ language construct that does what you want to do, and is part of the language library so it is already debugged.
Quite often, what you want to do is "common stuff", so debugging manual code will take more time than finding the appropriate pre-existing language construct, courtesy of your favorite internet search engine and/or stackoverflow itself. And being able to quickly find the language construct is also a very valuable skill.
In your case, function getline() takes an optional delimiter, which is a newline by default, but you can instead have "," as delimiter and so use getline() again, but to parse a single line. It just takes a string object pretending to be a file stream, that is an std::istringstream object.
So you end up with two nested loops, both using getline():
#include <sstream>
while (getline (dataFile, line)) {
std::istringstream iss{line};
std::string token;
while (getline (iss, token, ',')) {
std::cout << "DEBUG TOKEN LEN=" << token.length() << std::endl;
sVector.push_back(token);
}
// go build myWDG
}
That way, you don't have to mess up with lowly details such as the value of your commaPos variable. And the resulting code is easier to understand for another programmer.
Welcome to Stack Overflow.
Heads up: Sorry for the style, but you really have to learn solving those kind of problem on your own. It's called debugging. I'm experienced programmer and yet, my code never run exactly as I thought it will when testing it in the first time. You need to learn how to use a debugger like gdb or the built in debugger in the Visual C++ environment.
Now about your question:
The following code received the variable line with value Hello. There is no , character in line hence line = line.substr(commaPos + 1); return Hello all the time, and since 'Hello' string holds more then one character, you stuck in an infinte loop.
//Parse input file into string vector
while (line.length() >= 1) {
if (line.length() == 1) {
sVector.push_back(line);
break;
}
sVector.push_back(line.substr(0, commaPos));
line = line.substr(commaPos + 1);
commaPos = line.find(',');
}
The problem isn't stop there. Since each iteration over the infinite loop your program executing: sVector.push_back(line.substr(0, commaPos)); you actually allocates more and more memory, till you system won't give any more to this process. That's where you get the bad_alloc exception.
In other words, your error is not about C++, but about poor programing.
Reconsider your program, and think how you want to handle edge-cases like the Hello.
Oh, and never build objects on the stack. I know some places claim its OK to do this in the main function, but belive me its causing a lot of troubles.
I'm trying to write a program that first checks if a name is in a vector and if not then adds it to the vector. My code seems to have difficulties with parsing, at least that's what I get out of it. I tried changing the string to a char but it did not help me much.
#include <iostream>
#include <vector>
#include <string>
bool isinVector(std::string uElement, std::vector<std::string> uArray)
{
for (unsigned int i = 0; i <= sizeof(uArray); i++) {
if (uArray[i] == uElement) {
return true;
}
else {
return false;
}
}
}
int main()
{
bool trigger = false;
while (!trigger) {
std::vector<std::string> names;
names.push_back("Bart");
std::string newName;
getline(std::cin, newName);
if (isinVector(newName, names))
{
std::cout << "true" << std::endl;
trigger = true;
}
else
{
std::cout << "false" << std::endl;
names.push_back(newName);
for (int i = 0; i <= sizeof(names); i++) {
std::cout << names[i] << std::endl;
}
}
}
}
I made some adjustments to your code, removing your isinVector function and using a lambda inside the main function instead. In the future please provide a concise question and example.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::find_if;
int main(){
bool trigger = false;
while (!trigger) {
vector<string> names;
names.push_back("Bart");
string newName;
getline(cin, newName);
if(find_if(names.begin(), names.end(), [newName] (const string& name){
return !name.compare(newName);
}) != names.end()){
cout << "true" << endl;
trigger = true;
}
else{
cout << "false" << endl;
names.push_back(newName);
for (size_t i = 0; i < names.size(); i++) {
cout << names.at(i) << endl;
}
}
}
return 0;
}
The code uses std::find_if to check if the element exists in the vector. If std::find_f does not return the iterator to uArray.end() Then the element exists. Also your for loop used sizeof which is incorrect, use the vector.size method. And you were looping until <= , it should be < uArray.size() And it's safer to access elements in the vector through the .at method rather than an index [] since the .at will throw an out_of_range exception.
Among the things wrong in the updated post.
Improper use of sizeof
Reinventing a standard algorithm
Lack of error checking
Consider the tasks you're trying to accomplish. You want to:
Initialize a starting vector containing the name Bart
Continuously read new names. For each new name read:
a. Check to see if it is already in the vector.
if it is present terminate the read loop
else add it to the vector, and print the entire vector
This sequence of operations can be accomplished with stepwise refinement.
Step 1. Read names
First, you need to be able to continuously read names:
#include <iostream>
#include <string>
int main()
{
std::string name;
while (std::getline(std::cin, name))
std::cout << name << '\n';
}
Simple enough. Running this will echo any strings you type, one at a time, separated by newlines.
Step 2. Accumulate names in a vector
Next, we need to add a vector to hold the strings we're reading, with an initial population of the name "Bart". For this pass we'll be just putting every string we read into the vector
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
In addition to what was done prior, we're now accumulating strings in the vector, including duplicates, and reporting the vector content after each name read. This gets us closer to our stated goal.
Step 3: Conditional loop exit based on duplicate detection
Now we need to check for duplicates, and terminate the loop once it happens. We can do this using std::find. The final code is below:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
if (std::find(names.begin(), names.end(), name) != names.end())
break;
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
That's it. This is a simple task, but it lends itself nicely to an example of how you break a multi-part task down to manageable objectives , then build it in pieces.
Hope you found it useful.
Now my code looks like this:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
bool isinVector (std::string uElement, std::vector<std::string> uArray) {
bool invector = false;
std::vector<std::string>::iterator it = std::find(uArray.begin(),
uArray.end(),uElement);
if(it != uArray.end()){
invector = true;
}
return invector;
}
int main(){
bool trigger = false;
std::string name;
std::vector<std::string> names = { "Bart" };
while (std::getline(std::cin, name)){
if (isinVector(name, names)) {
std::cout << "true" << std::endl;
break;
}
else
{
std::cout << "false" << std::endl;
names.emplace_back(name);
}
}
return 0;
}
and it works, thanks a lot guys!
I am trying to get the array from my JSON Stinrg defined in the main function. I have used libjson API for this, simple key value is easy to get so I am able to get the value of RootA but how about this array in ChildA. Please let me know
#include <iostream>
#include <libjson/libjson.h>
#include <stdio.h>
#include <string.h>
using namespace std;
char rootA[20];
int childB;
int *childInt;
void ParseJSON(JSONNODE *n) {
if (n == NULL) {
printf("Invalid JSON Node\n");
return;
}
JSONNODE_ITERATOR i = json_begin(n);
while (i != json_end(n)) {
if (*i == NULL) {
printf("Invalid JSON Node\n");
return;
}
// recursively call ourselves to dig deeper into the tree
if (json_type(*i) == JSON_ARRAY || json_type(*i) == JSON_NODE) {
ParseJSON(*i);
}
// get the node name and value as a string
json_char *node_name = json_name(*i);
// find out where to store the values
if (strcmp(node_name, "RootA") == 0) {
json_char *node_value = json_as_string(*i);
strcpy(rootA, node_value);
cout << rootA<<"\n";
json_free(node_value);
} else if (strcmp(node_name, "ChildA") == 0) {
JSONNODE *node_value = json_as_array(*i);
childInt=reinterpret_cast<int *>(&node_value);
cout << childInt[0]<<"\n";
cout << childInt[1]<<"\n";
json_free(node_value);
} else if (strcmp(node_name, "ChildB") == 0) {
childB = json_as_int(*i);
cout << childB;
}
// cleanup and increment the iterator
json_free(node_name);
++i;
}
}
int main(int argc, char **argv) {
char
*json =
"{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":[1,2],\"ChildB\":42}}";
JSONNODE *n = json_parse(json);
ParseJSON(n);
json_delete(n);
return 0;
}
Thanks not-sehe but I got the solution for this
Ok I got it... treat array as a node and iterate over it again as if its a value with blank key. You can see the code part which did it..
if (json_type(*i) == JSON_ARRAY) {
cout << "\n Its a Json Array";
JSONNODE *arrayValue = json_as_array(*i);
JSONNODE_ITERATOR i1 = json_begin(arrayValue);
while (i1 != json_end(arrayValue)) {
cout << "\n In Array Loop ";
cout << json_as_int(*i1);
++i1;
}
}
This is probably not the answer you were looking for, but let me just demonstrate that a library with a slightly more modern interface makes this a lot easier (test.cpp):
#include <sstream>
#include "JSON.hpp"
int main()
{
auto document = JSON::readFrom(std::istringstream(
"{\"RootA\":\"Value in parent node\",\"ChildNode\":{\"ChildA\":[1,2],\"ChildB\":42}}"));
auto childA = as_object(
as_object(document)[L"ChildNode"]
)[L"ChildA"];
std::cout << childA << std::endl;
}
Which prints
[1,2]
It's using my own minimalist implementation of the rfc4627 specs. It's minimalist in interface only, supporting the full syntax and UNICODE.
The API interface is quite limited, but you can already see that working without C-style pointers, with proper dictionary lookups, key comparisons etc. makes it a less tedious and error prone:
// or use each value
for(auto& value : as_array(childA).values)
std::cout << value << std::endl;
// more advanced:
JSON::Value expected = JSON::Object {
{ L"RootA", L"Value in parent node" },
{ L"ChildNode", JSON::Object {
{ L"ChildA", JSON::Array { 1,2 } },
{ L"ChildB", 42 },
} },
};
std::cout << "Check equality: " << std::boolalpha << (document == expected) << std::endl;
std::cout << "Serialized: " << document;
See the full parser implementation (note: it includes serialization too) at github: https://github.com/sehe/spirit-v2-json/tree/q17064905