模板函数的意外结果

问题描述 投票:1回答:3

此代码不能给我预期的结果!怎么样?

template<typename T, std::enable_if_t < std::is_arithmetic_v<T>,bool> =true>
auto avr(T t)
{
    return t;
}
template<typename T,class ... C, std::enable_if_t<(std::is_arithmetic_v<T> &&...&& std::is_arithmetic_v<C>), bool> =true>
auto avr(T t,C...c)
{
    return (t + avr(c...)) / (sizeof...(c)+1);
}

int main()
{
    std::cout<<avr(1,5,3,7);

    return 0;
}

有人可以解释如何解决吗?

c++
3个回答
1
投票

因为每次除以sizeof时,不仅要除第一个,而且还应执行以下操作:

template<class ... C, std::enable_if_t<(...&& std::is_arithmetic_v<C>), bool> =true>
auto sum(C...c)
{
    return (c + ...);
}
template<typename T,class ... C, std::enable_if_t<(std::is_arithmetic_v<T> &&...&& std::is_arithmetic_v<C>), bool> =true>
auto avr(T t,C...c)
{
    return (t + sum(c...)) / (sizeof...(c)+1);
}

所以首先将数字求和,然后除(仅一次)


0
投票

有两个问题:

[First:增量均值需要您乘以sizeof...(c)进行每次更新

auto
avr(T t, C... c)
{
  return (t + sizeof...(c)*avr(c...)) / (sizeof...(c) + 1);
}

第二:必须使用avr(1., 5., 3., 7.),否则,对于avr(1, 5, 3, 7),您将使用整数运算并得到错误的结果

int
main()
{
  std::cout << avr(1., 5., 3., 7.);

  return 0;
}

通过这两个修改,您将获得预期的结果:4


0
投票

您应该递归地获得摘要,然后最后仅将其除以参数数量一次。

例如

template<typename T, std::enable_if_t < std::is_arithmetic_v<T>,bool> =true>
auto sum(T t)
{
    return t;
}
template<typename T,class ... C, std::enable_if_t<(std::is_arithmetic_v<T> &&...&& std::is_arithmetic_v<C>), bool> =true>
auto sum(T t,C...c)
{
    return t + sum(c...);
}
template<class ... C, std::enable_if_t<(... && std::is_arithmetic_v<C>), bool> =true>
auto avr(C...c)
{
    return sum(c...) / sizeof...(c);
}

借助fold expression(从C ++ 17开始),您可以

template<class ... C, std::enable_if_t<(... && std::is_arithmetic_v<C>), bool> =true>
auto avr(C...c)
{
    return (... + c) / sizeof...(c);
}
© www.soinside.com 2019 - 2024. All rights reserved.