...

Text file src/github.com/google/flatbuffers/docs/source/CppUsage.md

Documentation: github.com/google/flatbuffers/docs/source

     1Use in C++    {#flatbuffers_guide_use_cpp}
     2==========
     3
     4## Before you get started
     5
     6Before diving into the FlatBuffers usage in C++, it should be noted that
     7the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
     8to general FlatBuffers usage in all of the supported languages (including C++).
     9This page is designed to cover the nuances of FlatBuffers usage, specific to
    10C++.
    11
    12#### Prerequisites
    13
    14This page assumes you have written a FlatBuffers schema and compiled it
    15with the Schema Compiler. If you have not, please see
    16[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
    17and [Writing a schema](@ref flatbuffers_guide_writing_schema).
    18
    19Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
    20matter), you've generated a C++ header called `mygame_generated.h` using the
    21compiler (e.g. `flatc -c mygame.fbs`), you can now start using this in
    22your program by including the header. As noted, this header relies on
    23`flatbuffers/flatbuffers.h`, which should be in your include path.
    24
    25## FlatBuffers C++ library code location
    26
    27The code for the FlatBuffers C++ library can be found at
    28`flatbuffers/include/flatbuffers`. You can browse the library code on the
    29[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/include/flatbuffers).
    30
    31## Testing the FlatBuffers C++ library
    32
    33The code to test the C++ library can be found at `flatbuffers/tests`.
    34The test code itself is located in
    35[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
    36
    37This test file is built alongside `flatc`. To review how to build the project,
    38please read the [Building](@ref flatbuffers_guide_building) documentation.
    39
    40To run the tests, execute `flattests` from the root `flatbuffers/` directory.
    41For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
    42run: `./flattests`.
    43
    44## Using the FlatBuffers C++ library
    45
    46*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
    47example of how to use FlatBuffers in C++.*
    48
    49FlatBuffers supports both reading and writing FlatBuffers in C++.
    50
    51To use FlatBuffers in your code, first generate the C++ classes from your
    52schema with the `--cpp` option to `flatc`. Then you can include both FlatBuffers
    53and the generated code to read or write FlatBuffers.
    54
    55For example, here is how you would read a FlatBuffer binary file in C++:
    56First, include the library and generated code. Then read the file into
    57a `char *` array, which you pass to `GetMonster()`.
    58
    59```cpp
    60    #include "flatbuffers/flatbuffers.h"
    61    #include "monster_test_generate.h"
    62    #include <iostream> // C++ header file for printing
    63    #include <fstream> // C++ header file for file access
    64
    65
    66    std::ifstream infile;
    67    infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in);
    68    infile.seekg(0,std::ios::end);
    69    int length = infile.tellg();
    70    infile.seekg(0,std::ios::beg);
    71    char *data = new char[length];
    72    infile.read(data, length);
    73    infile.close();
    74
    75    auto monster = GetMonster(data);
    76```
    77
    78`monster` is of type `Monster *`, and points to somewhere *inside* your
    79buffer (root object pointers are not the same as `buffer_pointer` \!).
    80If you look in your generated header, you'll see it has
    81convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
    82
    83```cpp
    84    std::cout << "hp : " << monster->hp() << std::endl;              // '80'
    85    std::cout << "mana : " << monster->mana() << std::endl;          // default value of '150'
    86    std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
    87```
    88
    89*Note: That we never stored a `mana` value, so it will return the default.*
    90
    91The following attributes are supported:
    92
    93-   `shared` (on a field): For string fields, this enables the usage of string
    94    pooling (i.e. `CreateSharedString`) as default serialization behavior.
    95
    96    Specifically, `CreateXxxDirect` functions and `Pack` functions for object
    97    based API (see below) will use `CreateSharedString` to create strings.
    98
    99## Object based API  {#flatbuffers_cpp_object_based_api}
   100
   101FlatBuffers is all about memory efficiency, which is why its base API is written
   102around using as little as possible of it. This does make the API clumsier
   103(requiring pre-order construction of all data, and making mutation harder).
   104
   105For times when efficiency is less important a more convenient object based API
   106can be used (through `--gen-object-api`) that is able to unpack & pack a
   107FlatBuffer into objects and standard STL containers, allowing for convenient
   108construction, access and mutation.
   109
   110To use:
   111
   112```cpp
   113    // Autogenerated class from table Monster.
   114    MonsterT monsterobj;
   115
   116    // Deserialize from buffer into object.
   117    GetMonster(flatbuffer)->UnPackTo(&monsterobj);
   118
   119    // Update object directly like a C++ class instance.
   120    cout << monsterobj.name;  // This is now a std::string!
   121    monsterobj.name = "Bob";  // Change the name.
   122
   123    // Serialize into new flatbuffer.
   124    FlatBufferBuilder fbb;
   125    fbb.Finish(Monster::Pack(fbb, &monsterobj));
   126```
   127
   128The following attributes are specific to the object-based API code generation:
   129
   130-   `native_inline` (on a field): Because FlatBuffer tables and structs are
   131    optionally present in a given buffer, they are best represented as pointers
   132    (specifically std::unique_ptrs) in the native class since they can be null.
   133    This attribute changes the member declaration to use the type directly
   134    rather than wrapped in a unique_ptr.
   135
   136-   `native_default("value")` (on a field): For members that are declared
   137    "native_inline", the value specified with this attribute will be included
   138    verbatim in the class constructor initializer list for this member.
   139
   140-   `native_custom_alloc("custom_allocator")` (on a table or struct): When using the
   141    object-based API all generated NativeTables that  are allocated when unpacking
   142    your  flatbuffer will use "custom allocator". The allocator is also used by
   143    any std::vector that appears in a table defined with `native_custom_alloc`.
   144    This can be  used to provide allocation from a pool for example, for faster
   145    unpacking when using the object-based API.
   146
   147Minimal Example:
   148
   149schema:
   150
   151```cpp
   152    table mytable(native_custom_alloc:"custom_allocator") {
   153      ...
   154    }
   155```
   156
   157with `custom_allocator` defined before `flatbuffers.h` is included, as:
   158
   159```cpp
   160    template <typename T> struct custom_allocator : public std::allocator<T> {
   161
   162      typedef T *pointer;
   163
   164      template <class U>
   165      struct rebind {
   166        typedef custom_allocator<U> other;
   167      };
   168
   169      pointer allocate(const std::size_t n) {
   170        return std::allocator<T>::allocate(n);
   171      }
   172
   173      void deallocate(T* ptr, std::size_t n) {
   174        return std::allocator<T>::deallocate(ptr,n);
   175      }
   176
   177      custom_allocator() throw() {}
   178
   179      template <class U>
   180      custom_allocator(const custom_allocator<U>&) throw() {}
   181    };
   182```
   183
   184-   `native_type("type")` (on a struct): In some cases, a more optimal C++ data
   185type exists for a given struct.  For example, the following schema:
   186
   187```cpp
   188    struct Vec2 {
   189      x: float;
   190      y: float;
   191    }
   192```
   193
   194generates the following Object-Based API class:
   195
   196```cpp
   197    struct Vec2T : flatbuffers::NativeTable {
   198      float x;
   199      float y;
   200    };
   201```
   202
   203However, it can be useful to instead use a user-defined C++ type since it
   204can provide more functionality, eg.
   205
   206```cpp
   207    struct vector2 {
   208      float x = 0, y = 0;
   209      vector2 operator+(vector2 rhs) const { ... }
   210      vector2 operator-(vector2 rhs) const { ... }
   211      float length() const { ... }
   212      // etc.
   213    };
   214```
   215
   216The `native_type` attribute will replace the usage of the generated class
   217with the given type.  So, continuing with the example, the generated
   218code would use `vector2` in place of `Vec2T` for all generated code of
   219the Object-Based API.
   220
   221However, because the `native_type` is unknown to flatbuffers, the user must
   222provide the following functions to aide in the serialization process:
   223
   224```cpp
   225    namespace flatbuffers {
   226      Vec2 Pack(const vector2& obj);
   227      vector2 UnPack(const Vec2& obj);
   228    }
   229```
   230
   231-   `native_type_pack_name("name")` (on a struct when `native_type` is
   232    specified, too): when you want to use the same `native_type` multiple times
   233    (e. g. with different precision) you must make the names of the Pack/UnPack
   234    functions unique, otherwise you will run into compile errors. This attribute
   235    appends a name to the expected Pack/UnPack functions. So when you
   236    specify `native_type_pack_name("Vec2")` in the above example you now need to
   237    implement these serialization functions instead:
   238
   239```cpp
   240    namespace flatbuffers {
   241      Vec2 PackVec2(const vector2& obj);
   242      vector2 UnPackVec2(const Vec2& obj);
   243    }
   244```
   245
   246Finally, the following top-level attributes:
   247
   248-   `native_include("path")` (at file level): Because the `native_type` attribute
   249    can be used to introduce types that are unknown to flatbuffers, it may be
   250    necessary to include "external" header files in the generated code.  This
   251    attribute can be used to directly add an #include directive to the top of
   252    the generated code that includes the specified path directly.
   253
   254-   `force_align`: this attribute may not be respected in the object API,
   255    depending on the aligned of the allocator used with `new`.
   256
   257# External references
   258
   259An additional feature of the object API is the ability to allow you to load
   260multiple independent FlatBuffers, and have them refer to eachothers objects
   261using hashes which are then represented as typed pointers in the object API.
   262
   263To make this work have a field in the objects you want to referred to which is
   264using the string hashing feature (see `hash` attribute in the
   265[schema](@ref flatbuffers_guide_writing_schema) documentation). Then you have
   266a similar hash in the field referring to it, along with a `cpp_type`
   267attribute specifying the C++ type this will refer to (this can be any C++
   268type, and will get a `*` added).
   269
   270Then, in JSON or however you create these buffers, make sure they use the
   271same string (or hash).
   272
   273When you call `UnPack` (or `Create`), you'll need a function that maps from
   274hash to the object (see `resolver_function_t` for details).
   275
   276# Using different pointer types
   277
   278By default the object tree is built out of `std::unique_ptr`, but you can
   279influence this either globally (using the `--cpp-ptr-type` argument to
   280`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
   281pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
   282pointers. Unlike the smart pointers, naked pointers do not manage memory for
   283you, so you'll have to manage their lifecycles manually.  To reference the
   284pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
   285flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
   286
   287# Using different string type
   288
   289By default the object tree is built out of `std::string`, but you can
   290influence this either globally (using the `--cpp-str-type` argument to
   291`flatc`) or per field using the `cpp_str_type` attribute.
   292
   293The type must support `T::c_str()`, `T::length()` and `T::empty()` as member functions.
   294
   295Further, the type must be constructible from std::string, as by default a
   296std::string instance is constructed and then used to initialize the custom
   297string type. This behavior impedes efficient and zero-copy construction of
   298custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
   299per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
   300so that the custom string type is constructed by passing the pointer and
   301length of the FlatBuffers String. The custom string class will require a
   302constructor in the following format: `custom_str_class(const char *, size_t)`.
   303Please note that the character array is not guaranteed to be NULL terminated,
   304you should always use the provided size to determine end of string.
   305
   306## Reflection (& Resizing)
   307
   308There is experimental support for reflection in FlatBuffers, allowing you to
   309read and write data even if you don't know the exact format of a buffer, and
   310even allows you to change sizes of strings and vectors in-place.
   311
   312The way this works is very elegant; there is actually a FlatBuffer schema that
   313describes schemas (\!) which you can find in `reflection/reflection.fbs`.
   314The compiler, `flatc`, can write out any schemas it has just parsed as a binary
   315FlatBuffer, corresponding to this meta-schema.
   316
   317Loading in one of these binary schemas at runtime allows you traverse any
   318FlatBuffer data that corresponds to it without knowing the exact format. You
   319can query what fields are present, and then read/write them after.
   320
   321For convenient field manipulation, you can include the header
   322`flatbuffers/reflection.h` which includes both the generated code from the meta
   323schema, as well as a lot of helper functions.
   324
   325And example of usage, for the time being, can be found in
   326`test.cpp/ReflectionTest()`.
   327
   328## Mini Reflection
   329
   330A more limited form of reflection is available for direct inclusion in
   331generated code, which doesn't do any (binary) schema access at all. It was designed
   332to keep the overhead of reflection as low as possible (on the order of 2-6
   333bytes per field added to your executable), but doesn't contain all the
   334information the (binary) schema contains.
   335
   336You add this information to your generated code by specifying `--reflect-types`
   337(or instead `--reflect-names` if you also want field / enum names).
   338
   339You can now use this information, for example to print a FlatBuffer to text:
   340
   341    auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
   342
   343`MonsterTypeTable()` is declared in the generated code for each type. The
   344string produced is very similar to the JSON produced by the `Parser` based
   345text generator.
   346
   347You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
   348a convenient visitor/iterator so you can write your own output / functionality
   349based on the mini reflection tables without having to know the FlatBuffers or
   350reflection encoding.
   351
   352## Storing maps / dictionaries in a FlatBuffer
   353
   354FlatBuffers doesn't support maps natively, but there is support to
   355emulate their behavior with vectors and binary search, which means you
   356can have fast lookups directly from a FlatBuffer without having to unpack
   357your data into a `std::map` or similar.
   358
   359To use it:
   360-   Designate one of the fields in a table as they "key" field. You do this
   361    by setting the `key` attribute on this field, e.g.
   362    `name:string (key)`.
   363    You may only have one key field, and it must be of string or scalar type.
   364-   Write out tables of this type as usual, collect their offsets in an
   365    array or vector.
   366-   Instead of `CreateVector`, call `CreateVectorOfSortedTables`,
   367    which will first sort all offsets such that the tables they refer to
   368    are sorted by the key field, then serialize it.
   369-   Now when you're accessing the FlatBuffer, you can use `Vector::LookupByKey`
   370    instead of just `Vector::Get` to access elements of the vector, e.g.:
   371    `myvector->LookupByKey("Fred")`, which returns a pointer to the
   372    corresponding table type, or `nullptr` if not found.
   373    `LookupByKey` performs a binary search, so should have a similar speed to
   374    `std::map`, though may be faster because of better caching. `LookupByKey`
   375    only works if the vector has been sorted, it will likely not find elements
   376    if it hasn't been sorted.
   377
   378## Direct memory access
   379
   380As you can see from the above examples, all elements in a buffer are
   381accessed through generated accessors. This is because everything is
   382stored in little endian format on all platforms (the accessor
   383performs a swap operation on big endian machines), and also because
   384the layout of things is generally not known to the user.
   385
   386For structs, layout is deterministic and guaranteed to be the same
   387across platforms (scalars are aligned to their
   388own size, and structs themselves to their largest member), and you
   389are allowed to access this memory directly by using `sizeof()` and
   390`memcpy` on the pointer to a struct, or even an array of structs.
   391
   392To compute offsets to sub-elements of a struct, make sure they
   393are a structs themselves, as then you can use the pointers to
   394figure out the offset without having to hardcode it. This is
   395handy for use of arrays of structs with calls like `glVertexAttribPointer`
   396in OpenGL or similar APIs.
   397
   398It is important to note is that structs are still little endian on all
   399machines, so only use tricks like this if you can guarantee you're not
   400shipping on a big endian machine (an `assert(FLATBUFFERS_LITTLEENDIAN)`
   401would be wise).
   402
   403## Access of untrusted buffers
   404
   405The generated accessor functions access fields over offsets, which is
   406very quick. These offsets are not verified at run-time, so a malformed
   407buffer could cause a program to crash by accessing random memory.
   408
   409When you're processing large amounts of data from a source you know (e.g.
   410your own generated data on disk), this is acceptable, but when reading
   411data from the network that can potentially have been modified by an
   412attacker, this is undesirable.
   413
   414For this reason, you can optionally use a buffer verifier before you
   415access the data. This verifier will check all offsets, all sizes of
   416fields, and null termination of strings to ensure that when a buffer
   417is accessed, all reads will end up inside the buffer.
   418
   419Each root type will have a verification function generated for it,
   420e.g. for `Monster`, you can call:
   421
   422```cpp
   423	bool ok = VerifyMonsterBuffer(Verifier(buf, len));
   424```
   425
   426if `ok` is true, the buffer is safe to read.
   427
   428Besides untrusted data, this function may be useful to call in debug
   429mode, as extra insurance against data being corrupted somewhere along
   430the way.
   431
   432While verifying a buffer isn't "free", it is typically faster than
   433a full traversal (since any scalar data is not actually touched),
   434and since it may cause the buffer to be brought into cache before
   435reading, the actual overhead may be even lower than expected.
   436
   437In specialized cases where a denial of service attack is possible,
   438the verifier has two additional constructor arguments that allow
   439you to limit the nesting depth and total amount of tables the
   440verifier may encounter before declaring the buffer malformed. The default is
   441`Verifier(buf, len, 64 /* max depth */, 1000000, /* max tables */)` which
   442should be sufficient for most uses.
   443
   444## Text & schema parsing
   445
   446Using binary buffers with the generated header provides a super low
   447overhead use of FlatBuffer data. There are, however, times when you want
   448to use text formats, for example because it interacts better with source
   449control, or you want to give your users easy access to data.
   450
   451Another reason might be that you already have a lot of data in JSON
   452format, or a tool that generates JSON, and if you can write a schema for
   453it, this will provide you an easy way to use that data directly.
   454
   455(see the schema documentation for some specifics on the JSON format
   456accepted).
   457
   458Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
   459
   460There are two ways to use text formats:
   461
   462#### Using the compiler as a conversion tool
   463
   464This is the preferred path, as it doesn't require you to add any new
   465code to your program, and is maximally efficient since you can ship with
   466binary data. The disadvantage is that it is an extra step for your
   467users/developers to perform, though you might be able to automate it.
   468
   469    flatc -b myschema.fbs mydata.json
   470
   471This will generate the binary file `mydata_wire.bin` which can be loaded
   472as before.
   473
   474#### Making your program capable of loading text directly
   475
   476This gives you maximum flexibility. You could even opt to support both,
   477i.e. check for both files, and regenerate the binary from text when
   478required, otherwise just load the binary.
   479
   480This option is currently only available for C++, or Java through JNI.
   481
   482As mentioned in the section "Building" above, this technique requires
   483you to link a few more files into your program, and you'll want to include
   484`flatbuffers/idl.h`.
   485
   486Load text (either a schema or json) into an in-memory buffer (there is a
   487convenient `LoadFile()` utility function in `flatbuffers/util.h` if you
   488wish). Construct a parser:
   489
   490```cpp
   491    flatbuffers::Parser parser;
   492```
   493
   494Now you can parse any number of text files in sequence:
   495
   496```cpp
   497    parser.Parse(text_file.c_str());
   498```
   499
   500This works similarly to how the command-line compiler works: a sequence
   501of files parsed by the same `Parser` object allow later files to
   502reference definitions in earlier files. Typically this means you first
   503load a schema file (which populates `Parser` with definitions), followed
   504by one or more JSON files.
   505
   506As optional argument to `Parse`, you may specify a null-terminated list of
   507include paths. If not specified, any include statements try to resolve from
   508the current directory.
   509
   510If there were any parsing errors, `Parse` will return `false`, and
   511`Parser::error_` contains a human readable error string with a line number
   512etc, which you should present to the creator of that file.
   513
   514After each JSON file, the `Parser::fbb` member variable is the
   515`FlatBufferBuilder` that contains the binary buffer version of that
   516file, that you can access as described above.
   517
   518`samples/sample_text.cpp` is a code sample showing the above operations.
   519
   520## Threading
   521
   522Reading a FlatBuffer does not touch any memory outside the original buffer,
   523and is entirely read-only (all const), so is safe to access from multiple
   524threads even without synchronisation primitives.
   525
   526Creating a FlatBuffer is not thread safe. All state related to building
   527a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
   528outside of it is touched. To make this thread safe, either do not
   529share instances of FlatBufferBuilder between threads (recommended), or
   530manually wrap it in synchronisation primitives. There's no automatic way to
   531accomplish this, by design, as we feel multithreaded construction
   532of a single buffer will be rare, and synchronisation overhead would be costly.
   533
   534## Advanced union features
   535
   536The C++ implementation currently supports vectors of unions (i.e. you can
   537declare a field as `[T]` where `T` is a union type instead of a table type). It
   538also supports structs and strings in unions, besides tables.
   539
   540For an example of these features, see `tests/union_vector`, and
   541`UnionVectorTest` in `test.cpp`.
   542
   543Since these features haven't been ported to other languages yet, if you
   544choose to use them, you won't be able to use these buffers in other languages
   545(`flatc` will refuse to compile a schema that uses these features).
   546
   547These features reduce the amount of "table wrapping" that was previously
   548needed to use unions.
   549
   550To use scalars, simply wrap them in a struct.
   551
   552## Depth limit of nested objects and stack-overflow control
   553The parser of Flatbuffers schema or json-files is kind of recursive parser.
   554To avoid stack-overflow problem the parser has a built-in limiter of
   555recursion depth. Number of nested declarations in a schema or number of
   556nested json-objects is limited. By default, this depth limit set to `64`.
   557It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH`
   558definition. This definition can be helpful for testing purposes or embedded
   559applications. For details see [build](@ref flatbuffers_guide_building) of
   560CMake-based projects.
   561
   562## Dependence from C-locale {#flatbuffers_locale_cpp}
   563The Flatbuffers [grammar](@ref flatbuffers grammar) uses ASCII
   564character set for identifiers, alphanumeric literals, reserved words.
   565
   566Internal implementation of the Flatbuffers depends from functions which
   567depend from C-locale: `strtod()` or `strtof()`, for example.
   568The library expects the dot `.` symbol as the separator of an integer
   569part from the fractional part of a float number.
   570Another separator symbols (`,` for example) will break the compatibility
   571and may lead to an error while parsing a Flatbuffers schema or a json file.
   572
   573The Standard C locale is a global resource, there is only one locale for
   574the entire application. Some modern compilers and platforms have
   575locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
   576`strtoll_l`, `strtoull_l` to resolve this dependency.
   577These functions use specified locale rather than the global or per-thread
   578locale instead. They are part of POSIX-2008 but not part of the C/C++
   579standard library, therefore, may be missing on some platforms.
   580The Flatbuffers library try to detect these functions at configuration and
   581compile time:
   582- CMake `"CMakeLists.txt"`:
   583  - Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
   584- Compile-time `"/include/base.h"`:
   585  - `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
   586  - `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
   587
   588After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
   589set to `0` or `1`.
   590To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
   591or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
   592
   593To test the compatibility of the Flatbuffers library with
   594a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
   595```sh
   596>FLATBUFFERS_TEST_LOCALE="" ./flattests
   597>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
   598```
   599
   600## Support of floating-point numbers
   601The Flatbuffers library assumes that a C++ compiler and a CPU are
   602compatible with the `IEEE-754` floating-point standard.
   603The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
   604
   605### Support of hexadecimal and special floating-point numbers
   606According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
   607may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
   608The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
   609literals. The Flatbuffers library has a code to detect a compiler compatibility
   610with the literals. If necessary conditions are met the preprocessor constant
   611`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
   612The support of floating-point literals will be limited at compile time
   613if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
   614In this case, schemas with hexadecimal or special literals cannot be used.
   615
   616### Comparison of floating-point NaN values
   617The floating-point `NaN` (`not a number`) is special value which
   618representing an undefined or unrepresentable value.
   619`NaN` may be explicitly assigned to variables, typically as a representation
   620for missing values or may be a result of a mathematical operation.
   621The `IEEE-754` defines two kind of `NaNs`:
   622- Quiet NaNs, or `qNaNs`.
   623- Signaling NaNs, or `sNaNs`.
   624
   625According to the `IEEE-754`, a comparison with `NaN` always returns
   626an unordered result even when compared with itself. As a result, a whole
   627Flatbuffers object will be not equal to itself if has one or more `NaN`.
   628Flatbuffers scalar fields that have the default value are not actually stored
   629in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
   630Scalar fields with `NaN` defaults break this behavior.
   631If a schema has a lot of `NaN` defaults the Flatbuffers can override
   632the unordered comparison by the ordered: `(NaN==NaN)->true`.
   633This ordered comparison is enabled when compiling a program with the symbol
   634`FLATBUFFERS_NAN_DEFAULTS` defined.
   635Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
   636if GCC or Clang used. These compilers have a compile-time implementation
   637of `isnan` checking which MSVC does not.
   638
   639<br>

View as plain text