为C++概念示例添加std::array支持为何触发编译错误?
问题:std::array版本average函数模板参数推导失败的原因
在学习C++20概念时,基于cppreference的示例实现了针对std::vector的average模板函数,添加std::array的重载版本后,编译出现no matching function for call错误,提示模板参数推导失败,int与long long unsigned int不匹配。
原示例代码
template <typename T> requires std::integral<T> || std::floating_point<T> constexpr double average(std::vector<T> const &vec) { const double sum = std::accumulate(vec.begin(), vec.end(), 0.0); return sum / vec.size(); } int main() { std::vector sVec { 1, 2, 3, 4, 5}; assert(average(sVec) == 3); }
添加std::array支持后的代码
template <typename T, int size> // add size requires std::integral<T> || std::floating_point<T> constexpr double average(const std::array<T, size> &arr) { // use std::array<T, size> &arr) instead const double sum = std::accumulate(arr.begin(), arr.end(), 0.0); return sum / arr.size(); } int main() { std::array sArr { 1, 2, 3, 4, 5}; assert(average(sArr) == 3); }
编译错误信息
C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:65:19: 错误:找不到匹配的函数调用‘average(std::array<int, 5>&)’ 65 | assert(average(sArr) == 3); | ~~~~~~~^~~~~~ C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:14:18: 注意:候选函数:‘template<class T> requires (integral<T>) || (floating_point<T>) constexpr double average(const std::vector<T>&)’ 14 | constexpr double average(const std::vector<T> &vec) { | ^~~~~~~ C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:14:18: 注意:模板参数推导/替换失败: C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:65:19: 注意:‘std::array<int, 5>’并非派生自‘const std::vector<T>’ 65 | assert(average(sArr) == 3); | ~~~~~~~^~~~~~ C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:22:18: 注意:候选函数:‘template<class T, int size> requires (integral<T>) || (floating_point<T>) constexpr double average(const std::array<T, size>&)’ 22 | constexpr double average(const std::array<T, size> &arr) { | ^~~~~~~ C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:22:18: 注意:模板参数推导/替换失败: C:\Users\Cheng\OneDrive\Documents\Proj\HackerRank\Cpp\concept_introduction.cpp:65:19: 注意:类型‘int’与‘long long unsigned int’不匹配 65 | assert(average(sArr) == 3); | ~~~~~~~^~~~~~ Build finished with error(s).
错误原因
std::array的第二个模板参数是无符号整数类型(标准规定为std::size_t,通常对应unsigned long long或同级别无符号类型),但你在重载的模板函数中把第二个参数声明为int(带符号整数)。- 当你用类模板实参推导(CTAD)创建
std::array sArr {1,2,3,4,5};时,编译器推导得到的类型是std::array<int, 5>,这里的模板参数5是std::size_t类型的字面量。由于带符号整数和无符号整数属于不同类型,模板参数推导无法完成匹配,导致编译错误。
修复方案
将模板参数中的int size替换为std::size_t size(需要包含<cstddef>头文件),或者使用auto size让编译器自动推导参数类型:
方案1:使用std::size_t
#include <cstddef> // 引入std::size_t template <typename T, std::size_t size> requires std::integral<T> || std::floating_point<T> constexpr double average(const std::array<T, size> &arr) { const double sum = std::accumulate(arr.begin(), arr.end(), 0.0); return sum / arr.size(); }
方案2:使用auto自动推导
template <typename T, auto size> requires std::integral<T> || std::floating_point<T> constexpr double average(const std::array<T, size> &arr) { const double sum = std::accumulate(arr.begin(), arr.end(), 0.0); return sum / arr.size(); }
内容的提问来源于stack exchange,提问作者user747562
相关产品推荐
相关产品推荐

