2

我有这段代码,我试图从传递的参数中获取最大的数字。由于某种原因它不起作用,我不确定为什么。当我输入 2 个数字时,代码有效,但当传递 3 个或更多时,我收到以下错误:

prog.cpp: 在函数'int main()'中:
prog.cpp:31:29: 错误: 没有匹配函数调用'max(int, int, int)'<br> prog.cpp:31:29:注意:候选人是:
prog.cpp:24:30:注意:模板 constexpr decltype (handle::helper::max(max::args ...)) max(Args ...)
prog.cpp:24:30 : 注意: 模板参数推导/替换失败:
prog.cpp: 替换'模板 constexpr decltype (handle::helper::max(args ...)) max(Args ...) [with Args = {int, int, int}]':
prog.cpp:31:29: 从这里需要
prog.cpp:24:30: 错误: 没有匹配函数调用'handle::helper::max(int&, int&, int&)' <br> prog.cpp:24:30: 注意: 候选人是: prog.cpp:11:18: 注意: static T handle::helper::max(T, T) [with T = int; Args = {int, int}]
prog.cpp:11:18: 注意: 候选人需要 2 个参数,提供 3 个
prog.cpp:16:18: 注意: 静态 T 句柄::helper::max(T, T, Args ...) [with T =诠释; 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
}

谢谢大家!

4

2 回答 2

7

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...));
}


编辑:使用gcc's-std=c++1y标志(允许您发出尾随返回类型),您可以这样做。(上面的情况肯定是一个错误

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...));
}
于 2013-05-12T17:18:13.467 回答
1

一个问题是论点是错误的。你在打电话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...));
  }
};
于 2013-05-12T16:54:35.083 回答