{fmt}

时间:2018-10-29 22:40:20

标签: c++ templates typetraits one-definition-rule fmt

首先,我目前正在为自己的论文学习C ++,因此对该语言没有经验。任何帮助表示赞赏。

我在代码中使用了fmt库,可以通过专用于类模板类型fmt::formatter来规范用户提供的类型的格式。

示例

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

给出两个库AB,它们在实现时都碰巧使用了fmt,并且两者都以某种方式或其他方式需要打印/记录当前时间。 两者都可能合理地使用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进行打印。

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

问题

当我开发应用程序C并使用两个(不相关的)库AB时,我相信会有两个不同的相同类型的实现(即{{1} })从而违反了具有未定义行为的ODR。

问题

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

  1. 是否有一种方法可以避免在应用程序fmt::formatter<std::chrono::system_clock::time_point>中发生这种冲突,而又不改变上游的CA
  2. 如果可以修改BA(或两者)中的任何一个,则可以通过什么方式解决冲突或完全避免冲突。

1 个答案:

答案 0 :(得分:4)

  
      
  1. 是否有一种方法可以避免在应用程序C中发生这种冲突而又不改变上游的A和B?
  2.   

您确实违反了ODR,我认为您必须在不更改A和/或B的情况下避免冲突。

  
      
  1. 如果可以修改A或B(或两者),则可以通过什么方式解决冲突或完全避免冲突。
  2.   

仅专业化您自己的库的类型: 因此在库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相同。