Fra*_*ler 6 c++ templates stdvector
我有一个简单的函数模板来计算容器的平均值:
template<typename T>
T array_average( std::vector<T>& values ) {
if( std::is_arithmetic<T>::value ) {
if( !values.empty() ) {
if( values.size() == 1 ) {
return values[0];
} else {
return (static_cast<T>( std::accumulate( values.begin(), values.end(), 0 ) ) / static_cast<T>( values.size() ) );
}
} else {
throw std::runtime_error( "Can not take average of an empty container" );
}
} else {
throw std::runtime_error( "T is not of an arithmetic type" );
}
}
Run Code Online (Sandbox Code Playgroud)
我在static_cast<>上面添加了s,试图强制计算到所需的类型<T>.
当我在main中调用此函数时使用 uint64_t
std::vector<uint64_t> values{ 1,2,3,4,5,6,7,8,9,10,11,12 };
std::cout << array_average( values ) << '\n';
Run Code Online (Sandbox Code Playgroud)
此代码确实产生MSVC的编译器警告C4244可能由于转换而丢失数据,但它运行正常,这给了我预期的结果,并打印6到控制台.这是正确的,因为实际值是6.5由于整数除法中的截断6是正确的.
现在,如果我使用上面的函数代替:
std::vector<double> values { 2.0, 3.5, 4.5, 6.7, 8.9 };
std::cout << array_average( values2 ) << '\n';
Run Code Online (Sandbox Code Playgroud)
这应该给我一个结果,5.12但它显示4.6相反.这也给了我与上面相同的编译器警告,但它运行时没有运行时错误(执行中断)但是给我不正确的结果.
我不确定我的功能中的bug在哪里.我不知道这是否是由于编译器警告,或者是否是我设计函数本身的方式.
-编辑-
用户建议这可能是此Q/A的副本我不能反对它确实或不回答我的问题这一事实.在提出这个问题的时候; 我不知道这个错误来自于std::accumulate它本身的不当使用.我不确定它是否来自编译器警告,该警告涉及由于转换可能导致的数据丢失,或者我是否错误地投射,或者它是如何实现此功能的.在提供链接之前,我已经接受了此页面上的答案.我将保留此Q/A以供将来参考和读者使用!除此之外,我非常感谢提供的链接,因为它确实有助于了解错误在我的代码中的位置,错误是什么以及导致错误的原因,以及除了本页面上接受的答案之外如何正确修复错误.
Rei*_*ica 18
你static_cast是在错误的地方.你正在投射积累的结果,但让积累运行在初始术语的类型中(这里0,这是int).所以这样做:
return std::accumulate( values.begin(), values.end(), static_cast<T>(0) ) / static_cast<T>( values.size() );
Run Code Online (Sandbox Code Playgroud)
(注意4.6确实是结果static_cast<double>(2 + 3 + 4 + 6 + 8) / 5.0).
与问题核心无关的评论:
const std::vector<T>&,因为它不会修改values.T无效的函数调用该函数std::accumulate(例如,不是算术运算),则会出现编译时错误.最重要的if是必须以if constexpr你想要的方式工作.