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

时间:2013-05-12 16:35:37

标签: c++ templates c++11

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

  

prog.cpp:在函数'int main()'中:
  prog.cpp:31:29:错误:没有匹配函数来调用'max(int,int,int)'   prog.cpp:31:29:注意:候选人是:
  prog.cpp:24:30:注意:模板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:从这里要求
  prog.cpp:24:30:错误:没有匹配函数来调用'handle :: helper :: max(int&,int&,int&)'
  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:注意: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
}

谢谢大家!

2 个答案:

答案 0 :(得分: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个args的时候,这不会起作用。问题似乎是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的{​​{1}}标记(允许您发出尾随返回类型),您可以这样做。 (上面的案例绝对是一个错误

-std=c++1y

答案 1 :(得分: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...));
  }
};