Skip to content

[C++] Generated C++ code fails to compile maps with duration or timestamp keys #3787

Description

@BaldDemian

Search before asking

  • I had searched in the issues and found no similar issues.

Version

Latest Fory

Component(s)

C++

Minimal reproduce step

Consider this FDL:

package repro.temporal_key;

message Holder {
    map<duration, string> values = 1;
}

What did you expect to see?

The generated code should compile.

What did you see instead?

The generated code fails to compile.

Anything Else?

Root Cause

This bug is introduced by PR #3745. In this PR, we generate unordered_map for IDL's map type to match the behaviors of other languages.

But in C++, the key type of an unordered_map must be hashable.

Fory documents duration and timestamp as valid IDL map key types. Currently, Fory maps duration to fory::serialization::Duration and timestamp to fory::serialization::Timestamp. But these two types are just aliases for standard library types:

// ============================================================================
// Temporal Type Aliases
// ============================================================================
/// Duration: absolute length of time as nanoseconds
using Duration = std::chrono::nanoseconds;
/// Timestamp: point in time as nanoseconds since Unix epoch (Jan 1, 1970 UTC)
using Timestamp = std::chrono::time_point<std::chrono::system_clock,
std::chrono::nanoseconds>;

In C++17, these standard library types do not provide usable std::hash specializations, so std::unordered_map<fory::serialization::Duration, ...> and std::unordered_map<fory::serialization::Timestamp, ...> fail to compile.

date does not hit the same problem because Fory maps it to a Fory-owned Date type instead of a standard library alias. date can also hit the same problem.

Proposed Fix

Replace fory::serialization::Duration and fory::serialization::Timestamp from standard-library aliases with Fory-owned wrapper types.

Duration should store a normalized seconds/nanoseconds representation or total nanoseconds, and Timestamp should store seconds/nanoseconds since the Unix epoch.
These wrapper types should provide equality, ordering, and hash methods, so they can be used directly as unordered_map keys.

The serializers can keep the existing wire format unchanged by reading from and writing to the wrapper fields using the same seconds/nanoseconds encoding.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions