Skip to content

DISCUSSION: Adding support for formatting of integral types #15

@rtillery

Description

@rtillery

Being able to format integral types (e.g. F("{:4.2f}", 3.14159) => 3.14) would be a very nice feature.

Passing a format for a given type found during a specific serialization operation would be a start, but in practice, all elements of the same type don't always need the same formatting.

To make a solution as flexible as possible, one idea is to allow the user to provide a (sort-of*) map from a key to a callback function which can return the contextual-specific format string. Clearly such a map* is well beyond the current capabilities of {fmt} (or C++ std::format?) as a nested argument, so it would be necessary to add support for this as a first level fmt::formatter<> specialization:

template<>
struct fmt::formatter<fmtster::ElementFormat>
...

Another issue is that this map* needs to be maintained for all associated formatting operations, but not beyond.

So, the germ of an idea (based on a discussion with Victor Zverovich ({fmt} & std::format author) is to wrap the actual format string in the ElementFormat braces, and recursively call fmt::format() with the extracted string (and remaining arguments), maintaining the map* during that formatting, and then dispose of the map* upon return:

string fnDataPointFormat(double val)
{
    if (val < 1000.0)
        return "{:>6.2f}";
    else
        return "{:>10.2e}";
}

string fnConfigIndexFormat(int val)
{
    return "{:>2}";
}

fmtster::ElementFormatMap map =
{
    { "dataPoint*", &fnDataPointFormat },
    { "configIndex", &fnConfigIndexFormat }
};

cout << F("{:mydata:\n{:j,{},-b,1}\nmyconfig:\n{}}", fmtster::ElementFormat(map, mydata, style.value, myconfig)) << endl;

Clearly, all the type-ing and template-ing will require a lot of work.

Also, maintaining the map* for the duration of all the sub-calls is relatively easy, until multi-threaded applications are considered. Perhaps thread-local storage? Is there a C++ standard for that?

The callback specified for the key associated with an array could be called for each value in the array for conditional formatting (e.g. decimal vs engineering depending on magnitude of the value).

* The sort-of part is illustrated in the code above, where the (string-based) key can have wildcards. Efficiently ordering and searching such a map might be an interesting CS challenge.

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussionBrainstorming about possible feature or design approach

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions