有关常见错误 does not contain handler parameter named

本文探讨了在使用Struts框架进行表单提交时遇到的问题,特别是当未正确指定提交方式为POST时所引发的错误。文章列举了三个常见的错误来源,并强调了在不使用html:form标签的情况下明确设置method属性的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天也犯了这个错误.被郁闷了半天.

到最后原因是没有写POST方式.

主要是没有用html:form标签,直接用的form,就忘了这项了.

 

列一下这个错误的主要产生的根源:

1.struts-config.xml在ACTION属性里加上parameter="method",一般这个是不会忘的

2.action要继承DispatchAction

3.就是不用html:form标签时,一定要设置method="post"

<think>我们正在讨论C++模板中的包展开(packexpansion)错误错误信息“Pack expansiondoes notcontain anyunexpanded parameterpacks”通常发生在尝试展开一个参数包时,但该上下文中没有未展开的参数包。这个错误常见于以下几种情况:1.在需要参数包的地方忘记使用省略号(...)。2.在已经展开的包上再次展开。3.在没有任何参数包的上下文中使用包展开语法。我将通过几个例子来解释这个错误以及如何修复。示例1:忘记使用省略号```cpptemplate<typename... Ts> structMyStruct{//错误:这里没有使用...来展开Tsvoidfunc(Tst) {} };```修正:在函数参数中使用包展开```cpptemplate<typename...Ts>struct MyStruct {voidfunc(Ts...t){ }//正确:使用...展开Ts};```示例2:在已经展开的包上再次展开```cpptemplate<typename... Ts> voidfunc(Ts...args){//错误:args已经是一个展开的包,不能再次用...展开some_function(args......); }```修正:只需要展开一次```cpptemplate<typename... Ts> voidfunc(Ts...args){some_function(args...); //正确:展开参数包args}```示例3:在没有任何参数包的上下文中使用包展开```cpptemplate<typename T> voidfunc(Tt){//错误:这里没有参数包可以展开int arr[] ={t...};} ```修正:确保在模板参数包或函数参数包的上下文中使用包展开```cpptemplate<typename...Ts>void func(Ts... t) {intarr[]= {t...}; //正确:t是函数参数包}```示例4:在嵌套模板中错误使用```cpptemplate<typename...Ts>struct Outer{template<Ts...values>//错误:这里Ts是类型包,不能直接用于非类型模板参数structInner;}; ```修正:使用正确的包展开方式注意:非类型模板参数需要具体的类型和值。如果希望用一组类型对应的非类型参数,可以这样: ```cpptemplate<typename... Ts> structOuter {//假设Ts...中的每个类型都是整数类型,那么可以这样定义非类型参数包template<Ts...values>structInner;}; ```但是,这要求Ts中的每个类型都是允许的非类型模板参数类型(如整数、枚举、指针等)。如果Ts中包含不允许的类型,则无法使用。示例5:在using声明中错误展开```cpptemplate<typename... Ts> usingTuple= std::tuple<Ts>; //错误:没有展开Ts```修正:正确展开类型包```cpptemplate<typename...Ts>using Tuple= std::tuple<Ts...>; //正确```总结:包展开必须包含一个未展开的参数包,并且使用省略号(...)来展开它。在展开时,确保上下文允许展开(例如在函数参数、模板参数列表、初始化列表等中)。另外,注意每个包展开只能展开一个参数包,但可以同时展开多个包(如果它们长度相同)。下面是一个更复杂的例子,同时展开两个包(类型包和值包): ```cpptemplate<typename... Types, Types... Values> structMyStruct{//注意:这种用法在C++17及以后被允许,但要求Types和Values两个包长度相同};//或者使用auto来推导非类型模板参数的类型(C++17)template<auto...Values>struct AnotherStruct {};```但是,请注意,在同一个模板参数列表中同时展开类型包和非类型包需要谨慎,并且可能受到编译器支持的限制。最后,注意包展开的位置: -在函数调用中:func(args...)-在模板实例化中:MyType<Ts...>-在初始化列表中:{args...}-在基类列表中:classDerived :public Bases...{...} -在using声明中:using Base::operator()...;(C++17)如果遇到这个错误,请检查:1.是否在应该使用省略号的地方忘记了省略号。2.是否在已经展开的包上再次使用省略号。3.是否在没有参数包的上下文中使用了包展开。现在,让我们通过一个完整的例子来展示如何正确使用包展开:目标:实现一个函数,打印任意数量任意类型的参数。```cpp#include<iostream>//基础情况:没有参数时结束递归voidprint(){std::cout<< std::endl; }//递归打印函数template<typename T, typename... Ts> voidprint(Tfirst,Ts...rest){std::cout <<first <<" ";print(rest...);//包展开:将剩余参数展开传递给print} intmain(){print(1,2.5, "hello",'a');return0;} ```在这个例子中,我们使用了递归和包展开。注意在递归调用`print(rest...)`中,`rest...`就是一个包展开,它将参数包`rest`中的参数展开为逗号分隔的列表。但是,这个递归版本可能会因为递归深度过大而导致编译效率低或递归深度限制。我们可以使用折叠表达式(C++17)来改进: ```cpp#include<iostream> template<typename... Ts> voidprint(Ts...args){( (std::cout <<args <<" "), ...); //折叠表达式std::cout<< std::endl; }```这里,折叠表达式`( (std::cout <<args <<" "), ...)`实际上是一个二元折叠(一元向右折叠),它展开为:((std::cout <<arg1<< ""),(std::cout<< arg2 <<" ")), ...),(std::cout <<argN<< ""))。折叠表达式也是一种包展开,但更简洁高效。希望这些解释和示例能帮助你理解并解决“Pack expansiondoes notcontain anyunexpanded parameterpacks”错误。§§相关问题§§:1.什么是C++中的参数包(parameter pack)?2.折叠表达式(foldexpressions)在C++中如何工作?请举例说明。3.如何用模板元编程实现编译期计算参数包的大小?4.在C++中,如何将参数包展开为函数调用的参数?</think>### C++ 模板参数包展开错误:"Pack expansion does not contain any unexpanded parameter packs" 这个编译错误发生在使用 C++ 模板参数包时,编译器在需要展开参数包的位置找不到未展开的参数包。以下是详细解释和解决方案: #### 错误原因分析 1. **参数包未正确声明**: ```cpp template<typename T> void func(T... args) { // 错误:T 不是参数包 // ... } ``` 2. **错误的位置使用 `...`**: ```cpp template<typename... Ts> void func() { Ts... values; // 错误:不能在变量声明中直接使用... } ``` 3. **嵌套模板中忘记展开**: ```cpp template<typename... Ts> struct Outer { template<Ts> // 错误:缺少... struct Inner; }; ``` 4. **已展开的包再次展开**: ```cpp template<typename... Ts> void func(Ts... args) { process(args......); // 错误:双重展开 } ``` --- ### 解决方案与正确用法 #### 1. 正确声明参数包 ```cpp // 正确:使用 typename... 声明参数包 template<typename... Args> void print(Args... args) { (std::cout << ... << args) << '\n'; // 折叠表达式展开 } ``` #### 2. 正确的位置展开参数包 ```cpp template<typename... Ts> class Tuple { std::tuple<Ts...> data; // 正确:在模板实例化中展开 public: void print() { std::apply([](auto&&... args) { ((std::cout << args << " "), ...); // 正确:在折叠表达式中展开 }, data); } }; ``` #### 3. 嵌套模板的正确展开 ```cpp template<typename... Ts> struct Outer { // 正确:在非类型模板参数中展开 template<Ts... Values> struct Inner { static constexpr size_t size = sizeof...(Values); }; }; ``` #### 4. 参数包转发模式 ```cpp template<typename... Args> void forwarder(Args&&... args) { // 正确:单次展开转发 target_func(std::forward<Args>(args)...); } ``` --- ### 常见使用场景及代码示例 #### 场景1:创建变参模板类 ```cpp template<typename... Ts> struct TypeList { static constexpr size_t size = sizeof...(Ts); template<template<typename> class Transformer> using transform = TypeList<Transformer<Ts>...>; }; using MyList = TypeList<int, double, char>; using PtrList = MyList::transform<std::add_pointer_t>; // PtrList = TypeList<int*, double*, char*> ``` #### 场景2:变参函数模板 ```cpp template<typename... Ts> auto sum(Ts... values) { return (values + ...); // 折叠表达式求和 } int main() { std::cout << sum(1, 2.5, 3, 4.2); // 输出 10.7 } ``` #### 场景3:完美转发 ```cpp template<typename... Args> auto make_vector(Args&&... args) { return std::vector{std::forward<Args>(args)...}; } int main() { auto v = make_vector(1, 2.0, "hello"); // v 的类型是 std::vector<std::common_type_t<int, double, const char*>> } ``` #### 场景4:编译期判断 ```cpp template<typename... Ts> constexpr bool all_integral = (std::is_integral_v<Ts> && ...); static_assert(all_integral<int, short, char>); static_assert(!all_integral<int, double, char>); ``` --- ### 参数包展开规则总结 1. **展开位置**: - 模板参数列表 - 函数参数列表 - 基类列表 - 初始化列表 - 折叠表达式 - `using` 声明 2. **禁止展开位置**: - 普通变量声明 - 类成员声明 - 非模板上下文 3. **展开规则**: - 每个 `...` 展开最近的未展开参数包 - 一次展开只处理一个参数包 - 不同参数包需要分开展开 --- ### 调试技巧 1. **分步展开**: ```cpp template<typename... Ts> struct Debug { using Step1 = std::tuple<Ts...>; // 先展开到元组 using Step2 = Step1::element_type...; // 再从元组提取 }; ``` 2. **静态断言检查**: ```cpp template<typename... Ts> void func() { static_assert(sizeof...(Ts) > 0, "Pack is empty!"); // ... } ``` 3. **概念约束 (C++20)**: ```cpp template<typename... Ts> requires (std::is_arithmetic_v<Ts> && ...) auto sum(Ts... vals) { return (vals + ...); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值