可变参数模板实参推导错误:无法匹配参数中的integer结构体
问题:模板类integer的多对象相加失败
我有一个模板类integer,模板参数为整数值,想要实现n个该类对象的相加功能。单参数的基础情况可以成功获取整数值,但多参数情况执行失败。
原代码如下:
template <int Value> struct integer {}; template<int A, typename ...Rest> auto constexpr add(integer<A>, Rest...) { if constexpr (sizeof...(Rest) > 0) return A + add(Rest...); else return A; } int main(){ auto constexpr y = add(integer<1>{}); // 基础情况正常 auto constexpr x = add(integer<1>{}, integer<2>{}); // 多参数情况失败 return 0; }
我猜测元函数的参数存在问题,但无法确定具体问题。我认为应该可以推导参数为integer结构体,且不应实例化0参数的情况,但错误日志显示了相关问题:
(8, 17) : error C2144 : syntax error : 'integer<2>' should be preceded by ')' (19) : message: see reference to function template instantiation 'auto add<1,integer<2>>(integer<1>,integer<2>)' being compiled (8, 13) : error C2672 : 'add' : no matching overloaded function found (7, 1) : error C2780 : 'auto add(integer<Value>,Rest...)' : expects 2 arguments - 0 provided (7) : message: see declaration of 'add' (8, 17) : error C2144 : syntax error : 'integer<2>' should be preceded by ';' (7, 1) : error C2059 : syntax error : ')' (19, 52) : error C3313 : 'x' : variable cannot have the type 'const void'
问题分析
原代码的核心错误在于递归调用时的参数传递:
Rest...是类型参数包,递归调用add(Rest...)时,并没有传递任何实际的integer对象,相当于尝试调用无参的add,但你的模板要求至少一个参数,因此触发报错。- 另外,
Rest...没有限定为integer<...>类型,编译器无法从这些类型中提取对应的整数值进行累加。
解决方法
方法1:递归展开(兼容C++17及更早版本)
拆分基础情况和递归情况,明确接收integer类型的参数包,提取每个对象的模板参数值:
template <int Value> struct integer {}; // 基础情况:处理单个integer对象 template<int A> constexpr auto add(integer<A>) { return A; } // 递归情况:处理多个integer对象 template<int A, int... RestValues> constexpr auto add(integer<A>, integer<RestValues>...) { return A + add(integer<RestValues>{}...); } int main(){ constexpr auto y = add(integer<1>{}); // y = 1 constexpr auto x = add(integer<1>{}, integer<2>{}); // x = 3 return 0; }
方法2:C++17折叠表达式(更简洁)
利用C++17的折叠表达式直接累加所有integer的模板参数值,无需递归:
template <int Value> struct integer {}; template<int... Values> constexpr auto add(integer<Values>...) { return (Values + ...); // 左折叠累加所有Values } int main(){ constexpr auto y = add(integer<1>{}); // y = 1 constexpr auto x = add(integer<1>{}, integer<2>{}, integer<3>{}); // x = 6 return 0; }
内容的提问来源于stack exchange,提问作者user18263309
相关产品推荐
相关产品推荐

