将可变参数通过初始化列表传递给std::min时不起作用

编程语言 2026-07-09

我正在实现一个专门化版本的min(以及max),但在某些情况下它们应该直接调用原始的标准实现。这是我的代码:

#include <iostream>
#include <utility>

template <typename T>
concept Number = std::integral<T> || std::floating_point<T>;

template <Number T, typename... Args>
inline T min(T t, Args &&...args) {
    return std::min({t, std::forward<Args>(args)...});
}

int main() {
    return min(0, 1, 2, 3);
}

这在Windows上使用MSVC时运行良好,但在Linux的 libstdc++和 Clang上会抛出错误(lp 是一个浮点数组),见下文。

我并不真正理解这里的问题在哪里,较低级的错误信息提示需要比实际提供的参数更多的参数似乎也说不通。我应该如何修复?这段代码使用的是C++20

.../pstd.h:1402:12: error: no matching function for call to 'min'
 1402 |     return std::min({std::forward<Args>(args) ...});
      |            ^~~~~~~~
.../math.h:977:23: note: in instantiation of function template specialization 'pstd::min<float, float &, float &, float &>' requested here
  977 |         return {pstd::min(lp[0], lp[1], lp[2], lp[3]),
      |                       ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/bits/stl_algobase.h:232:5: note: candidate function template not viable: requires 2 arguments, but 1 was provided
  232 |     min(const _Tp& __a, const _Tp& __b)
      |     ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/bits/stl_algobase.h:280:5: note: candidate function template not viable: requires 3 arguments, but 1 was provided
  280 |     min(const _Tp& __a, const _Tp& __b, _Compare __comp)
      |     ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

解决方案

有一个简单的拼写错误:#include <algorithm> 缺失了:https://godbolt.org/z/adeYPP3rT

但为了让它更有趣(个人观点),这里给出一个既简化又改进的设计:

#include <algorithm>
#include <iostream>
#include <type_traits>

template <typename T>
concept Number = std::is_arithmetic_v<T>;

template <Number... Args>
inline std::common_type_t<Args...> min(Args... args) {
    return std::min({(static_cast<std::common_type_t<Args...>>(args))...});
}

int main() {
    double x = 1.3;
    std::cout << min(4, x, 2, 3);
}

LIVE

这将接受混合类型,否则初始化列表将不允许它。

为此,我还需要返回正确的类型,这个类型来自 std::common_type_t

这个概念我认为更接近实际意图,也不需要额外的模板参数 T

最终,我认为对这些类型使用转发引用是没有意义的(该操作是只读的,传递引用也不比拷贝值更省成本;然而如果想要支持更复杂的类型,这种设计将不够用)。

我可能忘记了一些边界情况或其他改进点。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章