如何避免 std 库的无效重载?

How to avoid an invalid overload from the std library?

在我使用的 C++14 项目中

#include <algorithm>
using std::max;            // for max(a,b)

但我还想提供一个 max() 函数,它接受任意数量的参数(相同类型)。为此,我添加了

template<typename T, typename...A>
constexpr inline T const& max(T const&x, T const&y, A...&&z)
{
    return max(max(x,y), std::forward<A>(z)...);
}

但是像

这样的电话
double x,y,z;
...
auto m = max(x,y,z);

编译器试图代替我的重载使用

namespace std {
template< class T, class Compare >
constexpr const T& max( const T& a, const T& b, Compare comp );
}

来自 algorithm。我怎样才能避免这种情况(但仍然提供预期的功能)?

(请注意,有一个 question about variadic min/max,但它并不能通过简单地将名称更改为 vmin/vmax 来解决我遇到的问题。)

如评论中所述,您可以简单地使用 std::max,它带有一个初始化列表。

一个示例调用是:

auto maxNum = std::max({a, b, c});

你不知道。

要么停止 using std::max 并限定您的名称空间,要么为您的函数命名。

问题可以通过仅重载 3 个或更多参数的函数来解决,例如:

template<typename T, typename...A>
constexpr inline T const& max(T const&x, T const&y, T const&z, A&&...w)
{
    return max(max(x,y), z, std::forward<A>(w)...);
}

我建议yao99 的答案应该被接受。出于好奇,我在这里向您展示一个通过您自己的命名空间提供适配器的解决方案。这只会使用 std::max 的二进制参数重载,因此不可能调用初始化程序列表重载。客户端代码仍然可以使用 max,如下所示:

适配器:

#include <iostream>
#include <algorithm>

namespace variadicMax
{
    // the variadic "max" recurses and reduces to a binary parameter version that we must implement
    template<typename T>
    constexpr inline T const& max(T const&x, T const&y)
    {
        return (std::max(x, y));
    }

    // the variadic overload recurses itself, removing two parameters (and adding one) each time.
    // Eventually it reduces to (x,y) which is handled by the other overload.
    template<typename T, typename...Args>
    constexpr inline T const& max(T const&x, T const&y, Args&&...z)
    {
        return (max (std::max(x, y), std::forward<Args>(z)...));
    }
};

客户:

// this is the only change needed in clients:
using variadicMax::max;

int main()
{
    double x, y, z, w, v;

    x = 1;  y = 2;  z = 3;  w = 4;  v = 5;
    auto m5 = max(x, y, z, w, v);  std::cout << m5 << std::endl;
    auto m5A = max(x, y, z, 4.0, v);  std::cout << m5A << std::endl;

    x = 1;  y = 2;  z = 3;
    auto m = max(x, y, z);  std::cout << m << std::endl;

    x = 2;  y = 3;  z = 1;
    auto m2 = max(x, y, z);  std::cout << m2 << std::endl;

    x = 3;  y = 2;  z = 1;
    auto m3 = max(x, y, z);  std::cout << m3 << std::endl;

    x = 3;  y = 2;
    auto m4 = max(x, y);  std::cout << m4 << std::endl;

    x = 3;  y = 2;
    auto m6 = max(3, 2);  std::cout << m6 << std::endl;

    x = 3;  y = 2;
    auto m7 = max(x, 2.0);  std::cout << m7 << std::endl;

    etc...