我正在尝试使用 {fmt}

问题描述

我有一个简单的模板,有点像:

template <typename T,T Min,T Max>
class LimitedInt {
public:
   static_assert(Min < Max,"Min must be less than Max");
   explicit LimitedInt(const T value)
   {
      setValue(value);
   }
   void setValue(const T value)
   {
      if (value < Min || value > Max) {
         throw std::invalid_argument("invalid value");
      }
      mValue = value;
   }
   T getValue() const
   {
      return mValue;
   }
private:
   T mValue{Min};
}

这允许我将其专门化为:

using Vlan = LimitedInt<uint16_t,4094>;

我希望能够用类似的东西格式化值

Vlan v{42};
fmt::format("{:04x}",v);

为此,我尝试将格式化职责作为 described here 转发给 formatter<int>,但一无所获。我的尝试看起来像:

namespace fmt {
template <>
struct formatter<LimitedInt> {
   formatter<int> int_formatter;
   template <typename ParseContext>
   constexpr auto parse(ParseContext& ctx)
   {
      return int_formatter.parse(ctx);
   }
   template <typename FormatContext>
   auto format(const LimtedInt& li,FormatContext& ctx)
   {
      return int_formatter.format(li.getValue(),ctx);
   }
};
}  // namespace fmt

我已经尝试了几种变体但都没有成功,错误往往围绕着这个:

In file included from /output/build/proj-local/src/networkinterface.h:8:0,from /output/build/proj-local/src/networkinterface.cpp:3:
/output/build/proj-local/src/limitedints.h:78:38: error: type/value mismatch at argument 1 in template parameter list for 'template<class T,class Char,class Enable> struct fmt::v7::formatter'
 struct formatter<LimitedInt> {
                                      ^
/output/build/proj-local/src/limitedints.h:78:38: note:   expected a type,got 'LimitedInt'

我目前的解决方法是拥有一个完整的格式化程序,它有自己的 parse()format() 方法,但对我来说,重新发明 Victor 已经编写的轮子似乎充其量是愚蠢的。

解决方法

适用通常的专业化规则。具体来说,您应该将 formatter 设为模板并将模板参数传递给 LimitedInt:

template <typename T,T Min,T Max>
struct fmt::formatter<LimitedInt<T,Min,Max>> {
  constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }

  auto format(const LimitedInt<T,Max>& val,format_context& ctx) {
    // Format val and write the output to ctx.out().
    return ctx.out();
  }
};

Godbolt:https://godbolt.org/z/Mnjsbc

,

我最终得到的是:

namespace fmt {
template <typename T,T Max>
struct formatter<LimitedInt<T,Max>> {
   formatter<int> int_formatter;
   constexpr auto parse(format_parse_context& ctx)
   {
      return int_formatter.parse(ctx);
   }
   auto format(const LimitedInt<T,Max>& li,format_context& ctx)
   {
      return int_formatter.format(li.getValue(),ctx);
   }
};
}  // namespace fmt

它通过了我所有的单元测试。一路上,我学到了更多关于 C++ 模板的知识。感谢 Werner、Igor 和 Victor,他们都帮助我指明了正确的方向。从 C 到 C++ 的过渡并不总是一帆风顺的。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...