1

I'm a c++ noob trying to build a personal finance websocket server that tracks all of my assets and liabilities in real-time.

I've found that I can make maps of maps to have a multi-dimensional system of key-value pairs.

I've also found that boost::any and boost::variant can be used to store multiple types for a values. My problem is that some levels aren't very complex compared to others. For example, a bank account will only have a value, the amount in the account, while a brokerage account will have many types of investments and characteristics, so I'd like to do something like (in json):

{
    'bankAccount': 100.00,
    'brokerageAccount': {
        'stocks': {
            'companyName': 'Stack Exchange',
            'ticker': 'STAK',
            'pps': bazillion
            ...

Where bankAccount and brokerageAccount can be inserted and erased when needed and discarded as necessary.

I don't really know where to go from here. When I try to put

map<string, boost::any> accounts;
accounts["cash"] = 100;
accounts["brokerageAccount"] = map<string, boost::any>;

in the private section of broadcast_server in this websocket server, gcc with these flags -I ~/websocketpp-master/ -std=c++0x -D_WEBSOCKETPP_CPP11_STL_ -D_WEBSOCKETPP_NO_CPP11_REGEX_ -lboost_regex -lboost_system -L/usr/lib -pthread -O0 -ljson_spirit gives error: ‘accounts’ does not name a type for the last two lines.

How best can I store data in a json type way above, with the ability to add and delete keys and values anywhere?

  • 1
    For reasons of debugging and efficiency, I would suggest you make real types for your data once you have a data model figured out. In the present, `unordered_map` (a hash table) may give you better performance than `map` (a balanced tree) for `string` keys. – Jon Purdy Sep 14 '13 at 19:56
  • @JonPurdy Thank you for the performance tip! Would you mind explaining what you mean by "real types"? I'm still very noob. Also, if you have a suggestion for a totally different methodology, absolutely please post it! I'm not married to this at all, I just want it to work all in one container so that I can have it all in one place without duplication of accounts, subaccounts, etc. Thank you so very much in advance! –  Sep 14 '13 at 20:01
  • 1
    I mean that the ability to add and remove values arbitrarily may help you *figure out* what you would like the structure of your data to be, but once you know that structure, you can create your own classes that model your specific problem. In particular, a class can enforce invariants on its values, such as numeric ranges. It is also a compile-time error to access nonexistent or wrongly typed data members. – Jon Purdy Sep 14 '13 at 20:29

2 Answers2

1
accounts["brokerageAccount"] = map<string, boost::any>;

You can not assign type to object. To fix problem add ()

accounts["brokerageAccount"] = map<string, boost::any>();

Variant that should be compiled correctly is:

#include <boost/any.hpp>
#include <map>
#include <string>

int main()
{
   std::map<std::string, boost::any> accounts;
   accounts["cash"] = 100;
   accounts["brokerageAccount"] = std::map<std::string, boost::any>();
}
fghj
  • 8,898
  • 4
  • 28
  • 56
  • Thank you very much for your help with this! Do you know how to do this? http://stackoverflow.com/questions/18808339/set-access-jagged-map-values-made-with-mapstring-boostany?lq=1 I very much appreciate it in advance! –  Sep 15 '13 at 15:31
1

map<string, boost::any> on the last line is a type, not an object of that type. You have to call the constructor of that type to create an argument. Change the last line to

accounts["brokerageAccount"] = map<string, boost::any>();

This fixes it on my copy of Visual Studio 2010

Cort Ammon
  • 10,221
  • 31
  • 45