{fmt} 中基于特征的定制点和 ODR 违规问题

Trait based customisation points and ODR-violation concerns in {fmt}

首先,我目前正在为我的论文学习 C++,因此对这门语言没有经验。感谢任何帮助。

我在我的代码中使用 fmt 库,格式化用户提供的类型的规范方式是通过专门化 class 模板类型 fmt::formatter.

例子

编译器资源管理器中的代码:https://godbolt.org/z/2VO_wa

给定两个库 AB,这两个库恰好在其实现中大量使用 fmt 并且都以某种方式或其他方式需要 print/log 当前时间。 两者都可能合理地使用 std::chrono::system_clock 并且想要在几个点格式化它,每个定义自己的 fmt::formatter<std::chrono::system_clock::time_point> 版本以使这个简单的代码成为可能:

auto msg = fmt::format("It is now {}", std::chrono::system_clock::now());

A 使用与 B 不同的实现,因为它考虑了本地时区而不是 UTC 打印。

现在这个例子非常具体,但是由于 class 模板 fmt::formatter 是格式化用户提供的类型的方式,所以这种情况可能以一种或另一种形式出现。

问题

当我开发我的应用程序 C 并同时使用(不相关的)库 AB 时,我相信会有两个相同类型的不同实现(即 fmt::formatter<std::chrono::system_clock::time_point>) 因此违反了具有未定义行为的 ODR。

问题

假设我理解正确,我的两个问题是:

  1. 有没有办法在不改变 AB 上游的情况下避免应用程序 C 中的这种冲突?
  2. 如果可以修改 AB(或两者),则可以通过哪些方式解决或完全避免冲突。
  1. Is there a way to avoid this conflict in the application C without altering A and B upstream?

你确实违反了ODR,我认为你不改变A就可以避免冲突and/or B.

  1. If either A or B (or both) can be modified, in what ways can the conflict be resolved or fully prevented.

仅专门化您自己的库的类型: 所以在库 A 中,围绕 std::chrono::system_clock::time_point

创建包装器
 namespace A {
     struct TimePoint {
         std::chrono::system_clock::time_point timePoint;
     };
 }


namespace fmt {
     // Specialization of formatter<TimePoint>
}

然后

auto msg = fmt::format("It is now {}", A::TimePoint{std::chrono::system_clock::now()});

图书馆 B 也一样。