在任意加长的集合中查找最大数不起作用

Finding max number in an arbitrarily-lengthened set isn't working

本文关键字:查找 最大数 不起作用 集合 任意加      更新时间:2023-10-16

我有这段代码,其中我试图从传递的参数中获得最大的数字。由于某种原因,它不起作用,我不太确定原因。当我输入2个数字时,代码工作,但当传递3个或更多数字时,我得到这些错误:

prog.cpp: In function ' int main() ':
Prog.cpp:31:29:错误:没有匹配的函数来调用max(int, int, int)
Prog.cpp:31:29:备注:candidate is:
prog.cpp:24:30: note: template constexpr decltype (handle::helper::max(max::args…))max(args…)
Prog.cpp:24:30:注意:模板参数演绎/替换失败:
prog.cpp:在替换' template constexpr decltype (handle::helper::max(args…))max(args…)[with args = {int, int, int}] ':
Prog.cpp:31:29: required from here
Prog.cpp:24:30:错误:调用' handle::helper::max(int&, int&, int&) '时没有匹配的函数
Prog.cpp:24:30:注:候选人是:prog.cpp:11:18: note: static T handle::helper::max(T, T) [with T = int;Args = {int, int}]
Prog.cpp:11:18:注意:候选人期望2个参数,提供3个
prog.cpp:16:18:注:static T handle::helper::max(T, T, Args…)[with T = int;Args = {int, int}]
Prog.cpp:16:18:注意:候选人期望4个参数,提供3个

程序如下:

#include <iostream>
namespace handle
{
    template <typename... Args>
    struct helper {};
    template <typename T, typename... Args>
    struct helper<T, Args...>
    {
        static T constexpr max(T x, T y)
        {
            return x > y ? x : y;
        }
        static T constexpr max(T x, T y, Args... args)
        {
            return max(x, max(y, args...));
        }
    };
}
template <typename... Args>
static auto constexpr max(Args... args) -> decltype(handle::helper<Args...>::max(args...))
{
    return handle::helper<Args...>::max(args...);
}
int main()
{
    std::cout << max(5, 3, 7); // fails
}

我真的很困惑,因为我以为我已经记下了。我做错了什么?我该如何改正?谢谢。


更新:谢谢命名。既然这个问题现在已经解决了,下面是结果:

#include <type_traits>
#include <iostream>
namespace handle
{
    template <typename T, typename V>
    static auto constexpr max(T const& x, V const& y)
    -> typename std::common_type<T, V>::type
    {
        return x > y ? x : y;
    }
    template <typename T, typename V, typename... Args>
    static auto constexpr max(T const& x, V const& y, Args const&... args)
    -> typename std::common_type<T, typename std::common_type<V, Args...>::type>::type
    {
        return max(x, max(y, args...));
    }
}
template <typename... Args>
static auto constexpr max(Args const&... args) -> decltype(handle::max<Args...>(args...))
{
    return handle::max<Args...>(args...);
}
int main()
{
    std::cout << max(5, 3, 7.8, 2, 4, 55); // 55
}

谢谢大家!

Morwenn已经指出你的问题了。但是,您仍然可以将代码简化为这样。(你确实可以在c++ 11中专门化函数模板)

namespace handle
{
    template <typename T, typename V>
    static auto max(const T& x, const V& y)  
    -> typename std::common_type<T,V>::type
    {
        return x > y ? x : y;
    }
    template <typename T, typename V, typename... Args>
    static auto max(const T& x, const V& y, const Args&... args) 
    -> decltype( max(x, max(y, args...)) )
    {
        return max(x, max(y, args...));
    }
}
int main()
{
    std::cout << handle::max(1,2,3.3); 
}

这样做的好处是在比较不同类型时返回正确的类型。


编辑:显然,当你有超过3个参数时,这将不起作用。问题似乎是gcc在计算

时没有考虑可变的max本身。
decltype(max(y, args...) 

你可以妥协,用这个代替

template <typename T, typename V, typename... Args>
static auto max(const T& x, const V& y, const Args&... args) 
 -> typename std::common_type<T, V>::type
{
    return max(x, max(y, args...));
}

0x499602D2在评论中建议的更好的方法

template <typename T, typename V, typename... Args>
static auto max(const T& x, const V& y, const Args&... args)
-> typename std::common_type<T, V, Args...>::type
{
    return max(x, max(y, args...));
}


EDIT:使用gcc-std=c++1y标志(允许您发出尾随返回类型),您可以这样做。(上面的例子肯定是一个bug,然后)

template <typename T, typename V>
auto max(const T& x, const V& y) {
    return x > y ? x : y;
}
template <typename T, typename V, typename... Args>
auto max(const T& x, const V& y, const Args&... args) {
    return max(x, max(y, args...));
}

一个问题是参数是错误的。你正在呼叫helper<int,int,int>::max。在你的模板中:

template <typename T, typename... Args>
struct helper<T, Args...>
{
    constexpr static T max(T x, T y)
    {
        return x > y ? x : y;
    }
    constexpr static T max(T x, T y, Args... args)
    {
        return max(x, max(y, args...));
    }
};

Args变成了int,int,所以你最终得到一个有两个参数的max函数,一个有四个参数的max函数,但是没有一个有三个参数的。

然而,这并不像删除一个参数那么简单:

    constexpr static T max(T x, Args... args)
    {
        return max(x, max(args...));
    }

因为现在你的函数与max(x,y)变得模糊了。

你可以做的是提供这样的专门化:

template <typename T>
struct helper<T> {
  static T max(T x) { return x; }
};
template <typename X,typename Y,typename... Args>
struct helper<X,Y,Args...> {
  constexpr static X max(X x,Y y,Args... args)
  {
    return std::max(x,helper<Y,Args...>::max(y,args...));
  }
};