c++ - C++20 格式化程序模板重定义错误
问题描述
我正在尝试做的事情:定义两个fmt::formatter
模板,一个用于派生自的类型,std::exception
一个用于派生自的类型,std::array<char, N>
以便我可以将这些类型作为参数传递给使用fmt::format()
.
问题:当我只定义一个格式化程序模板时,一切都按预期工作,但是当我定义两者时,我收到一个错误,指出我正在重新定义一个类型:
error: redefinition of ‘struct fmt::v7::formatter<T, char, void>’
代码示例:
template<typename T>
concept Exception = std::is_base_of_v<std::exception, T>;
template<std::size_t arrayLen>
template<typename T>
concept CharArray = std::is_base_of_v<std::array<char, arrayLen>, T>;
template <Exception T>
struct fmt::formatter<T> {
constexpr auto parse(format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const T& ex, FormatContext& ctx) {
return format_to(ctx.out(), "{}", ex.what());
}
};
template <CharArray T>
struct fmt::formatter<T> {
constexpr auto parse(format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const T& arr, FormatContext& ctx) {
const std::string str{arr.data(), strnlen(arr.data(), arr.size())};
return format_to(ctx.out(), "{}", str);
}
};
开发环境: g++ 11.1.0,CentOS,fmt
来自<spdlog/fmt/bundled/format.h>
我尝试过的:我尝试定义 Exception 和 CharArray 这两个概念,使它们相互排斥。我尝试使用 CharArray 以外的概念,它不是在 size 参数上模板化的。我测试了具有两个void foo(T)
功能,一个是模板化的Exception
,一个是CharArray
按预期工作的。
我在寻找什么:在这一点上,我对解释我做错了什么比对潜在的解决方法更感兴趣。如果涉及到这一点,我有几个解决方法,但我真的想弄清楚我的误解在哪里,这样我就可以从中吸取教训。
提前感谢您的帮助,请在您的回复中保持友好。
解决方案更新:我错误地定义了这个CharArray
概念,它没有被 GCC 捕获。fmt
由于 GCC 错误,我还需要将模板移动到命名空间内。
解决方案
这个:
template<std::size_t arrayLen>
template<typename T>
concept CharArray = std::is_base_of_v<std::array<char, arrayLen>, T>;
不是有效的声明。我很惊讶编译器没有将其标记为明显格式错误(报告为102289)。
你只能得到一个模板头concept
(你可以编写多个这样template
的声明的唯一地方是当你在类主体之外定义类模板的成员函数模板时,或者其他类似的东西)。
你可以用 C++20 编写这个概念的方式是:
template <std::size_t N>
void f(std::array<char, N> const&);
template <typename T>
concept CharArray = requires (T t) { f(t); }
基本上,如果你可以f(t)
用 a调用T
,那么这意味着t
要么是某种,std::array<char, N>
要么继承自其中。借助 C++20 中的额外 lambda 特性,我们甚至可以将其放入概念本身:
template <typename T>
concept CharArray = requires (T t) {
[]<std::size_t N>(std::array<char, N> const&){}(t);
};
这里的 lambda 只是为了执行与我们对自由函数模板所做的相同的“可调用”检查。
推荐阅读
- splunk - 从 Splunk 搜索查询调用外部 rest api
- java - Hibernate java Criteria查询具有多个集合成员(如标签)的实例
- angular - Angular 6 - 当我更改标签时,来自可观察的数据不会改变
- javascript - 使用 push 方法向对象添加条件
- ruby-on-rails - 分页限制了我的 csv 导出
- c# - 在 C# 中将 2 个本地字符串 [] 添加到单个数组中
- django - 关于如何使用 Django 实现用鼠标在网站上绘制图片的能力的教程
- android - 我可以在 ndk 中使用带有 libc++ 的实验文件系统吗
- r - R:采样:校准函数:svd(X)中的错误:'x'中的无限或缺失值
- teradata - 具有易失性表和输入参数的存储过程