On 14 Jan 2016 at 13:02, Gottlob Frege wrote:
I've experimented with static_map quite a bit. But never with C++11/14, unfortunately.
Some thoughts:
- once you have static_map, the next thing you immediately want is bi_map - to offer two way lookup. - and from there, you want multiple keys and columns: - and maybe projection functions as well:
Added to the project idea at https://svn.boost.org/trac/boost/wiki/SoC2016, thank you.
I'm not sure, however, what the usage looks like for the bimap and multimap cases. It is no longer the simple syntax of mapvar[a] = b;
Easy if type Key != type Value OR if type Key == type Value and key != value, but implicit in a bimap is you can't modify anything at all, the map is 100% const. That still has wide use cases.
Possibly due to limitations with pre-11 C++, I had a two-step process for declaring/defining the map:
// the map is this type typedef static_map ab_map;
// but the data/table is an array of this type: // using the inner element_type means you don't repeat A,B (more robust to changes) static ab_map::table_entry_type ab_table[] = { { a1, b1 }, { a2, b2 }, ... };
// the actual map:
ab_map theMap = ab_table; // constructor does magic
Doing a bi-map is fairly easy above, as table_entry_type can actually be { A, B, reverse_index } but the { a1, b1 } initialization is still valid as the reverse_index gets initialized to 0. The reverse_index is basically an extra hidden column.
Constexpr probably gets rid of many of those problems.
Very interesting, especially as you've tapped exactly where I got this GSoC project idea from. In the post peer review AFIO v2 rewrite I have this new concept of "storage profiles" which is an empirically determined set of characteristics about file i/o on some given combination of filing system, disk drive, disk controller, motherboard, CPU and OS version. Each storage profile is a static map of const char *keys to some type T which can be any of std::string, unsigned long long, unsigned int, float etc. and can be written or loaded from a YAML database. The concept is that a "standard" YAML database can be kept in the AFIO distro for quick lookup of common system configurations, but for uncommon configurations a suite of tests can be run to figure out the profile for some given storage combo. This lets AFIO v2 become less conservative on some systems. For example, if a system guarantees atomic updates for 4Kb write bursts if and only if on a 4Kb aligned boundary (this is very common on PCIe systems) but otherwise only guarantees atomic updates to a 64 byte burst on a 64 byte aligned boundary, AFIO can dispense with explicit byte range locking in a much wider range of use cases. Anyway, AFIO v2's storage_profile looks a bit like this: //! A (possibly incomplet) profile of storage struct BOOST_AFIO_DECL storage_profile { ... item<unsigned long long> mem_quantity = { "system:mem:quantity", &system::mem }; item<float> mem_in_use = { "system:mem:in_use", &system::mem }; // Controller characteristics itemstd::string controller_type = { "storage:controller:kind", &storage::device }; item<unsigned> controller_max_transfer = { "storage:controller:max_transfer", storage::device, "The maximum number of bytes the disk controller can transfer at once" }; item<unsigned> controller_max_buffers = { "storage:controller:max_buffers", storage::device, "The maximum number of scatter-gather buffers the disk controller can handle" }; ... }; So what we are doing is to use in-class initialisation to default construct all these member variables to their YAML section plus key, an address of a function capable of figuring out that value through testing, and an optional description text. This syntax makes it dead easy to add new items to the profile, simply add another in-class initialised member variable and voila it's done. Now as much as the above is great, I am still not happy with this design of storage_profile because I have to duplicate the YAML text key and the variable name which seems unnecessary in C++ 14. I would much prefer a static map of text keys to type erased value instead where storage_profile["storage:controller:max_buffers"].set_value(5); ... does *exactly* the right thing because the compiler, entirely at compile time, turns the string key lookup into a storage location of an unsigned value in storage_profile, so I would expect the assembler generated by the compiler by the above statement to look something like: mov r0, #5 str r0, [storage_profile + #offset ] ... and that is entirely it. A proposed constexpr static map would deliver exactly what I am looking for, and I for one would be pleased. tl;dr; I think we are on exactly the same page with the same use case and problem to be solved here. Unsurprising seeing as we used to work in the same team :) Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/