New features as of version 1.7.0 Sept. 2016 ***SOME BREAKAGE MAY OCCUR!! (See below)*** Top-Level: * Printing more resolution of floats and doubles (so doesn't lose precision) * The op[] for Val is having trouble when using const Val objects. * InformativeError in occonforms.h needs inline marker Discussion: ******* PRECISION OF FLOATS AND DOUBLES WHEN PRINTING ***************** **As of PicklingTools 1.7.0 (this release) we are printing floats/doubles in higher precision, so some outputs may have more significant figures when printed. This is so that going through a string WON'T lose any precision. The example below shows going from real_8 -> string -> real_8 can lose precision (unless we change the precision to 17 places). real_8 a = 1.2345678912345654321; // uses all bits Val v = a; char filename[] = "/tmp/junkreal"; WriteValToFile(v, filename); // Writes out human readable string Val vresult; ReadValFromFile(filename, vresult); // Reads human readable string real_8 result = vresult; if (a==result) { cout << "OK" << endl; } else { cout << "Lost precision going to the File and string!" << endl; } We had to extend to precision for doubles to 17 digits, and floats to 9 digits so we don't lose any information going to a string file. See the test C++/opencontainers_1_8_5/tests/precision_test.cc for more information. YOU CAN STILL GET OLD BEHAVIOUR BY SETTING TWO MACROS FROM THE COMMAND LINE (Changing the macros OC_DBL_DIGITS and OC_FLT_DIGITS): -DOC_DBL_DIGITS=16 -DOC_FLT_DIGITS=7 We feel the newer behavior is more correct because you won't lose any information going back and forth between strings and reals. ************* CALLING OPERATOR[] ON A CONST VAL ******************* **Using non-const methods on a const object should give a compiler error. As expected, line 4 below (t["a"]) fails to compile because operator[] is a non-const method (because it can CHANGE the Val!) // This all works as expected const Tab tt("{'a':666}"); cout << tt("a") << std::endl; /// compiles okay cout << tt["a"] << endl; /// FAILS to compile, but that's correct We expect similar behavior with Val: // This all compiles??? Check line 4! const Val t = Tab("{'a':666}"); cout << t("a") << std::endl; /// compiles okay cout << t["a"] << endl; /// compiles OKAY??? NOT GOOD!! What happens is that the compiler looks for a const method on Val so it can find something to make this compile. And it finds "operator int_8() const" conversion (which is a const method). So: cout << t["a"] << endl; // is equivalent to ... int_8 tmp = t.operator int_8(); cout << tmp["a"] << endl; // This compiles? How can that compile, you ask? An old, sometimes forgotten piece of C lore helps explain: char *a = "abc"; int i; cout << a[i] << endl; // These both compile?? cout << i[a] << endl; Because: a[i] == *(a + i) == *(i + a) == i[a]; In other words, (const char* + int) is the same operation as (int + const char*): it's just pointer arithmetic. We WANT a compiler error! So, there are two ways to do this. operator [] (int) const = delete; // Newer C++ operator [] (int const; // NO IMPLEMENTATION PROVIDED So, if we provide a prototype operator[] that's const. then the compiler has no choice but to match that method (and it won't match the "operator int_8() const" method). However, since there's no implementation, a link error will occur, basically saying "Hey, you are trying to call [] on a const object! No implementation provided!". The message looks something like: val_test.cc:28: undefined reference to `OC::Val::operator[](char const*) const' The "=delete" gives a better error message, and happens at compile time rather than link-time (but it's still definitely not run-time). The only problem: the "=delete" only works on newer C++ compilers. We still have just enough users at RedHat 6 with an older compiler that we have to support the less optimal "NO IMPL PROVIDED" way. But, the most important thing: WE GET AN ERROR BEFORE RUN-TIME on either platform. With the OC_DELETE_OPBRACKET_CONST macro, you can choose to select the =delete version. From the compile line: -DOC_DELETE_OPBRACKET Details: C++: * Moved to opencontainers 1.8.5 * Updated version numbers * Updated resolution of double and float strinigize to 17 and 9 (resp.). * Added tests/precision_test.cc to show how the problem can manifest (if you don't have 17 and 9 digits). Affects a number of tests. * Updated ocval.h to provide "empty" implementations for operator[] const (for Val). See Discussion above. Allow using =delete (instead of empty impl) with a macro for people with newer compilers: OC_DELETE_OPBRACKET * Updated ocforms.h so InformativeError is inline M C++/opencontainers_1_8_5/include/ocport.h M C++/opencontainers_1_8_5/include/ocval.h M C++/opencontainers_1_8_5/tests/conform_test.output M C++/opencontainers_1_8_5/tests/items_test.output M C++/opencontainers_1_8_5/tests/iter_test.output M C++/opencontainers_1_8_5/tests/maketab_test.output M C++/opencontainers_1_8_5/tests/otab_test.output M C++/opencontainers_1_8_5/tests/pretty_test.output M C++/opencontainers_1_8_5/tests/proxy_test.output M C++/opencontainers_1_8_5/tests/runall M C++/opencontainers_1_8_5/tests/ser_test.output M C++/opencontainers_1_8_5/tests/tab_test.output M C++/opencontainers_1_8_5/tests/valbigint_test.output M C++/opencontainers_1_8_5/tests/valreader_test.output M CHANGES A C++/opencontainers_1_8_5/tests/precision_test A C++/opencontainers_1_8_5/tests/precision_test.cc A C++/opencontainers_1_8_5/tests/precision_test.output