Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么总和是0?_C++_Templates_C++11_G++_Variadic Templates - Fatal编程技术网

C++ 为什么总和是0?

C++ 为什么总和是0?,c++,templates,c++11,g++,variadic-templates,C++,Templates,C++11,G++,Variadic Templates,我正在尝试创建一个通用求和函数模板。此模板将是左关联的。下面是我的实现 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, t

我正在尝试创建一个通用求和函数模板。此模板将是左关联的。下面是我的实现

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

}
int结果=0;
样板
常数T&sum\U助手(常数D&D、常数T&v){
结果=结果+v;
返回结果;
}
整数传递(…){}
样板
自动求和辅助程序(常量D&D、常量T1&v1、常量Ts&…参数)->decltype(v1+sum\u辅助程序(D、参数…){
返回v1+sum_helper(d,参数…);
}
A类{};
样板
结构序列{};
样板
自动求和(const Ts&…params)->decltype(求和助手(A(),params…)
{
返回过程((sum_helper(seq(),params))…,1);
}

但是当我像
sum(1,2,3,4)
那样调用它时,它总是输出
0
。怎么了?我知道应该纠正
pass
。但是如何纠正呢?

这里有一个更简单的解决方案:

#include <iostream>

using namespace std;

template <typename T1>
auto _sum(T1 & _ret, const T1 & _t1) -> T1
{
    _ret += _t1;
    return _ret;
}

template <typename T1, typename... Ts>
auto _sum(T1 & _ret, const T1 & _t1, const Ts &... params) -> T1 
{
    _ret += _t1;
    return _sum(_ret, params...);
}

template <typename T1, typename... Ts>
auto sum(const T1 & _t1, const Ts &... params) -> T1 
{
    T1 ret = _t1;
    return _sum(ret, params...);    
}

int main()
{
    cout << sum(1, 2, 3, 4, 5) << endl;
    return 0;
}
#包括
使用名称空间std;
样板
自动求和(T1和ret,常数T1和T1)->T1
{
_ret+=_t1;
返回(ret);;
}
样板
自动求和(T1和ret,常数T1和T1,常数Ts和…参数)->T1
{
_ret+=_t1;
返回_sum(_ret,params…);
}
样板
自动求和(常数T1&_T1,常数Ts&…参数)->T1
{
T1 ret=_T1;
返回_sum(返回、参数…);
}
int main()
{
库特
但当我把它叫做和(1,2,3,4)时,它总是输出0。怎么了

这是因为
pass
不返回任何内容,所以这里的是未定义的行为,因为您是从非空函数流出的,没有返回任何内容

我不知道你为什么需要在这里通过
pass

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


然而,一个更简单的版本是

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);    
}
模板
T总和(常数T&v){
返回v;
}
样板
自动求和(常数T1和v1,常数T2和v2)->decltype(v1+v2){
返回v1+v2;
}
样板
自动求和(常数T1和v1、常数T2和v2、常数Ts和…rest)->decltype(v1+v2+sum(rest…){
返回v1+v2+和(剩余…);
}
int main(){

cout原始答案不起作用,因为后面的返回类型在其声明点之前使用了重载。在知道函数的返回类型之前,也不可能向前声明函数。因此我们需要一个helper结构。下面是起作用的(不幸的是现在非常复杂)版本

#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...);
}
#包括
样板
结构求和;
/*这是基本情况*/
样板
结构sum_impl
{
typedef decltype(std::declval()+std::declval())结果类型;
静态结果类型doit(常数T1和v1,常数T2和v2)
{
返回v1+v2;
}
};
/*这是左结合性的递归定义*/
样板
结构sum_impl
{
typedef decltype(std::declval()+std::declval())步骤类型;
typedef typename sum_impl::result_type result_type;
静态结果类型doit(常数T1和v1、常数T2和v2、常数Ts和…rest)
{
返回和impl::doit(v1+v2,rest…);
}
};
样板
typename sum\u impl::result\u type sum(常量Ts&…参数)
{
返回sum_impl::doit(args…);
}
演示:


以下是一个版本,它保留了Named答案的简单性,但保留了关联性:

/* 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... );
}
/*实际上不需要,除非有人只想用一个参数调用sum*/
样板
T总和(常数T&v)
{
返回v;
}
/*这是基本情况*/
样板
自动求和(常数T1和v1,常数T2和v2)->decltype(v1+v2)
{
返回v1+v2;
}
/*这是左结合性的递归定义*/
样板
自动求和(常数T1和v1,常数T2和v2,常数Ts和…rest)->decltype(求和(v1+v2,rest…)
{
返回和(v1+v2,其余…);
}

pass/seq的作用是什么?谢谢!你能解释一下它是如何左联想的吗?@footy:因为它计算
1+(2+3+4+5)
。请注意,左关联通常不会修复求值顺序。我在重载+运算符后对对象尝试了以下操作。它表示
模板参数推断/替换失败
。如何操作?我无法理解1+(…)是右关联的。左关联将是(…)+5.@Rollie在重载+运算符后,我对对象尝试了以下操作。它说模板参数推断/替换失败..怎么做?我无法理解我认为您的解决方案对
sum(1,2,3)
;或任何奇数个参数都不起作用;它将转到变量和并调用
1+2+sum(3)
,和
sum(3)
未定义。@Rollie是的。我已经修复了它。我在sum的长版本中选择两个参数的原因是因为gcc无法扣除
decltype(v1+sum(rest…)
由于某些原因,它是正确的。当有两个参数匹配,其余的参数已展开时,它会匹配。@footy什么类型的错误消息?您要添加什么类型的对象?是的,看起来比我的好:P@Ben这太棒了!几乎正确。但是如果我给出超过4个论点,它似乎失败了compile@footy:,这是因为这条小路ing返回类型使用递归,但它在当前重载的声明点之前。其他答案不是也同样失败吗?而且,看起来有人已经解决了这个问题:
/* 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... );
}