Changes between Version 7 and Version 8 of SoC2016


Ignore:
Timestamp:
Jan 17, 2016, 9:26:35 PM (7 years ago)
Author:
Niall Douglas
Comment:

Improved static_map description

Legend:

Unmodified
Added
Removed
Modified
  • SoC2016

    v7 v8  
    5858==== Background ====
    5959
    60 Even with all of Boost's facilities ![1] and using C++ 14, this program represents the currently best available method
     60Even with all of Boost's facilities and using C++ 14, this program represents the currently best available method
    6161of implementing a static constant associative map of keys to values
    62 ([http://melpon.org/wandbox/permlink/SEt61EAxVG4J5BnF play with it in an online compiler here]):
     62([http://melpon.org/wandbox/permlink/SEt61EAxVG4J5BnF play with it in an online compiler here] and
     63[https://goo.gl/gTZOEp see the assembler generated here]):
    6364
    6465{{{
     
    110111for keys (which has linear complexity to number of items per lookup), or we can ''copy'' at runtime the
    111112associative array into an associative map which can thereafter be queried at runtime in either `O(log N)`
    112 or `O(1)` complexities respectively.
     113or `O(1)` complexities respectively. Both these options generate very significant amounts of runtime code.
    113114
    114115Almost every seasoned C++ programmer has at least once (and often many times throughout a career) written
    115116a static constant associative map which is initialised once from static constant data usually at process
    116 start, and is thereafter never modified. Given that C++ 14 can very easily implement a static constant
    117 associative map container class, it would be a very worthwhile addition to Boost and C++ in general if
     117start, and is thereafter never modified. Given that C++ 14 can implement an associative map where key
     118lookups are constexpr when possible, it would be a very worthwhile addition to Boost and C++ in general if
    118119we gained a high quality implementation of a static map class.
    119120
    120 ![1]: ''Probably'' Boost.Hana which is expected to enter Boost soon could be used to implement a
    121 static map which can be queried either at compile time or run time fairly easily. This project proposal
    122 does not require the use of Boost.Hana, though using it may be interesting.
    123 
    124121
    125122==== GSoC project proposal ====
    126 1. To seek consensus from the Boost Developer's mailing list on a suitable design for a Boost `static_map` class.
    127  (The chances are high that the `static_map` class would be STL compliant much as other constexpr-capable STL
    128  containers such as `std::array<>` and `std::initializer_list<>`).
     1231. To seek consensus from the Boost Developer's mailing list on a suitable design for a Boost `static_map` class
     124 with the following design features:
     125 1. Whose number of items and keys are completely fixed from construction onwards.
     126 2. All features of which can be used in constant expressions (i.e. all member functions are marked constexpr).
     127 3. Which can be completely statically initialised in the mind of the compiler, or in static global storage.
     128 4. Values, though not keys nor number of items, are modifiable.
     129 5. Which performs constexpr key to value lookup ''to the maximum possible extent''.
     130
     131 It turns out this list of requirements is in fact quite challenging to implement, and even seasoned Boost
     132 programmers have to stop and ponder this one. To demonstrate the difficulty in code:
     133
     134 {{{
     135#!c++
     136constexpr std::pair<int, const char *> map_data[] = {
     137  { 5, "apple" },
     138  { 8, "pear" },
     139  { 0, "banana" }
     140};
     141// Easy: generates no runtime code
     142constexpr auto cmap = make_static_map(map_data);
     143// Easy: generates no runtime code, this is as if literal "apple"
     144constexpr const char *what_is_5 = cmap[5];
     145
     146// Challenging: needs to only generate code loading immediately from a memory location.
     147// It must NOT generate any additional runtime overhead like hashing nor searching.
     148const char *what_is_8 = cmap[8];
     149}}}
     150 
     151 The reason why the last statement is challenging is because of the rules of when a constexpr-capable code path is
     152 executed by the compiler: the compiler only ''has'' to constexpr execute when all the inputs are constant
     153 expressions '''and''' all the outputs will be used in constant expressions, and it only ''may'' constexpr execute
     154 when all the inputs are constant expressions. Indeed empirical testing of clang 3.7 and VS2015 found both currently
     155 do '''not''' constexpr execute when the result is not stored constexpr, so in a naive implementation the last
     156 statement '''does''' generate a runtime lookup on current compiler technology despite the constant expression inputs.
     157 If you'd like to see more detail about this specific problem, have a look at the assembler generated for a toy
     158 static_map implementation at https://goo.gl/eO7ooa.
    129159
    1301602. To implement a `static_map` class which runs on at least two major C++ compilers.
    131   - The class should be entirely a compile-time implementation via constexpr and generate no runtime overhead
    132     whatsoever.
     161  - Hopefully in C++ 14, however upcoming features in C++ 1z do make the problem considerably easier to fix.
    133162
    1341633. To implement a comprehensive unit test suite for the `static_map` class, including tests ensuring no
    135  runtime overhead is generated.
     164 runtime overhead is generated for the challenging use case exampled above.
    136165
    1371664. To configure per-commit continuous integration for the unit test suite on at least one of the major public
     
    139168
    1401695. To write documentation to Boost quality levels for the new container class, including time and space complexity
    141  guarantees and exception guarantees for each API and each use of each API.
     170 guarantees and benchmarks, and exception guarantees for each API and each use of each API.
    142171
    143172==== Potential project extension funded by Boost ====
    144173- `static_multimap` (keys are not unique)
    145174- `static_set` and `static_multiset` (keys only)
    146 - `static_ordered_map` and `static_ordered_multimap` (iteration is in order of keys)
     175- `static_ordered_map` and `static_ordered_multimap` (iteration is in lexical order of keys)
    147176- `static_bimap` (values are also keys)
    148177- `static_index<T...>` (multi-column table with some columns being hash indexed)