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: '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&)' の呼び出しに一致する関数がありません<br> prog.cpp:24:30: 注: 候補は次のとおりです: prog.cpp:11:18: 注: static T ハンドル::helper::max(T, T) [with T = int; Args = {int, int}]
prog.cpp:11:18: 注: 候補は 2 つの引数を期待し、3 つの引数が提供される
prog.cpp:16:18: 注: 静的 T ハンドル::ヘルパー::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
}

私はこれを持っていると思っていたので、私は本当に混乱しています。私は何を間違っていますか?どうすれば修正できますか? ありがとう。


更新: Named さんに感謝します。この質問は現在解決されているため、結果は次のとおりです。

#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-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

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ため、max2 つのパラメーターmaxを受け取る関数と 4 つのパラメーターを受け取る関数ができますが、3 つのパラメーターを受け取る関数はありません。

ただし、引数の 1 つを削除するだけでは簡単ではありません。

    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 に答える