0

一般的な合計関数テンプレートを作成しようとしています。このテンプレートは になりますleft associative。以下は私の実装です

    int result=0;
template <typename D, typename T>
const T &sum_helper(const D &d, const T &v) {
    result=result+v;
    return result;
}
int pass(...){}

template <typename D, typename T1, typename... Ts>
auto sum_helper(const D &d, const T1 &v1, const Ts &... params) -> decltype(v1 + sum_helper(d, params...)) {
    return v1 + sum_helper(d, params... );
}

class A {};

template <typename... Ns> 
struct seq {};

template <typename... Ts>
auto sum(const Ts &... params) -> decltype(sum_helper(A(), params...)) 
{
    return  pass((sum_helper(seq<Ts...>(),params)) ...,1);

}

しかし、私がそれを呼び出すと、常にsum(1,2,3,4)出力され0ます。どうしたの?私はそれpassが修正されるべきであることを知っています。しかし、それを修正する方法は何ですか?

4

3 に答える 3

3

末尾の戻り値の型は、宣言のポイントの前にオーバーロードを使用するため、元の答えは機能しません。また、戻り値の型を知る前に関数を前方宣言することは不可能です。したがって、ヘルパー構造体が必要です。これが機能する(残念ながら現在は非常に複雑な)バージョンです

#include <utility>

template <typename...>
struct sum_impl;

/* This is the base case */
template <typename T1, typename T2>
struct sum_impl<T1, T2>
{
    typedef decltype(std::declval<const T1&>() + std::declval<const T2&>()) result_type;

    static result_type doit(const T1& v1, const T2& v2)
    {
        return v1 + v2;
    }
};

/* And here is the recursive definition for left-associativity */
template <typename T1, typename T2, typename... Ts>
struct sum_impl<T1, T2, Ts...>
{
    typedef decltype(std::declval<const T1&>() + std::declval<const T2&>()) step_type;
    typedef typename sum_impl<step_type, Ts...>::result_type result_type;

    static result_type doit(const T1& v1, const T2& v2, const Ts&... rest)
    {
        return sum_impl<step_type, Ts...>::doit(v1 + v2, rest...);
    }
};

template <typename... Ts>
typename sum_impl<Ts...>::result_type sum(const Ts&... args)
{
    return sum_impl<Ts...>::doit(args...);
}

デモ: http://ideone.com/jMwgLz


Named's answer の単純さを保持しているが、関連付けられたままのバージョンを次に示します。

/* not really needed, unless someone wants to call sum with only a single argument */
template <typename T>
T sum(const T& v)
{
    return v;
}

/* This is the base case */
template <typename T1, typename T2>
auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2 )
{
    return v1 + v2;
}

/* And here is the recursive definition for left-associativity */
template <typename T1, typename T2, typename... Ts>
auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( sum(v1 + v2, rest...) )
{
    return sum(v1 + v2, rest... );
}
于 2013-05-13T01:48:30.540 に答える
1

しかし、 sum(1,2,3,4) のように呼び出すと、常に 0 が出力されます。どうしたの?

これは、何も返さないpassためです。何も返さずに非 void 関数から流出しているため、ここにあるのは未定義の動作です。

passなぜあなたがここに必要なのかわかりません

return  pass((sum_helper(seq<Ts...>(),params)) ...,1);

可変引数を展開して直接 に送信できますsum_helper。このような

return  sum_helper(seq<Ts...>(),params...);


ただし、より単純なバージョンは

template <typename T>
T sum(const T& v) {
    return v;
}

template <typename T1, typename T2>
auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2) {
    return v1 + v2;
}

template <typename T1, typename T2, typename... Ts>
auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( v1 + v2 + sum(rest...) ) {
    return v1 + v2 + sum(rest... );
}

int main() {
    cout << sum(1,2,3,4);    
}

Rollie's answer では、さらに単純なバージョンが提供されています。

于 2013-05-10T21:24:12.980 に答える