为什么`fmt/core.h`中的`count()`函数重载是这样实现的?

Hon*_*y.W 4 c++ fmt

在 中fmt/core.h,我注意到该函数使用带有给定谓词的count_named_args()模板函数。count

我发现版本的重载版本count很奇怪:

template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {
  return (B1 ? 1 : 0) + count<B2, Tail...>();
}
Run Code Online (Sandbox Code Playgroud)

为什么我们需要使用模板参数bool B2来显式提取下一个布尔值,而不是直接使用参数包bool... Tail

如果我删除这些bool B2内容,然后尝试编译:

template <bool B1, bool... Tail> constexpr auto count() -> size_t {
  return (B1 ? 1 : 0) + count<Tail...>();
}
Run Code Online (Sandbox Code Playgroud)
static_assert(count<false>() == 0);
static_assert(count<true, false>() == 1);
Run Code Online (Sandbox Code Playgroud)

当参数数量减少到最后一个时,它会给出一个错误,因为确定重载是不明确的:

size_t count<false,>(void) noexcept
size_t count<false>(void) noexcept
Run Code Online (Sandbox Code Playgroud)

Qui*_*mby 5

查看当前的 main,有两个函数模板:

template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }
template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {
  return (B1 ? 1 : 0) + count<B2, Tail...>();
}
Run Code Online (Sandbox Code Playgroud)

如果那些是

template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }
template <bool B1, bool... Tail> constexpr auto count() -> size_t {
  return (B1 ? 1 : 0) + count<Tail...>();
}
Run Code Online (Sandbox Code Playgroud)

然后对于 call count<false>(),两个候选者都会被考虑,并且根据重载解析规则,两者都不比另一个更专业 -> 歧义。请记住,参数包可以为空。为什么有一个额外的参数包不被认为不那么专业,我真的不知道。

仅具有<bool B1, bool... Tail>不适用于零参数,并且count对于这种情况具有额外的非模板不适用于count<pack...>()pack为空的极端情况。另一方面,由于默认值,<bool B = false>仍然可以像这样调用。count()

我认为<bool B = false>and<bool B1, bool B2, bool... Tail>是最通用、最简单的解决方案。