我想要有2个方法,一个是SetVariable,另一个是MyClass中的GetVariable 两者都将接收一个枚举和参数,参数可以不止一种,也可以不止一种类型 并根据枚举调用相关的私有方法 我想从另一个名为 OtherClass 的类中调用这些方法 (这些不是真实姓名,只是为了解释) 我与 ChatGPT 进行三合一,它告诉我有关可变模板的信息,但问题是我得到了错误的参数编号错误
template <typename... Args>
bool SetVariable(const int& variable, Args&&... args)
{
auto returnValue = false;
switch (variable)
{
case 1:
{
returnValue = Function1(std::forward<Args>(args)...);
break;
}
case 2:
{
returnValue = Function2(std::forward<Args>(args)...);
break;
}
default:
break;
}
return returnValue;
}
这既是函数 1 又是函数 2:
Function1( const int & axis_, const double& velocity_ )
Function2( std::vector<int>& chameleonFirmwareVec_ )
这就是我从不同的类调用 SetVariable 的方式
bool Core::OtherClass::Function1Call( const int & axis_, const double& velocity_ )
{
return MyClass.SetVariable(1, axis_, velocity_);
}
这里的错误是 Function2':函数不接受 2 个参数 而且我根本不会调用它,如果我有不止一种情况错误安培
但问题是我得到了错误的参数编号错误
问题在于,所示
switch
中任何分支内的代码都必须有效,无论该分支代码是否被执行。
如果可以在编译时决定选择哪个分支,则可以使用
constexpr if
。
问题是这里的枚举值(
variable
)是在运行时确定的,而参数的类型(Args
)是在编译时确定的。
因此,当调用
SetVariable(1, axis_, velocity_)
时,编译器会生成一个函数SetVariable(int, double)
的模板实例化,而这个函数包含对Function2(int, double)
的调用,而该函数并不存在。这会导致编译错误。
避免这种情况的两种方法是使参数类型也由运行时确定,或者使枚举编译时确定。
要使参数的类型由运行时确定,一种方法是这样设置:
using AxisVelocity = std::pair<int, double>;
void SetVariable(
int variable,
const std::variant<
AxisVelocity,
std::vector<int>
>& value
) {
if(variable == 1) {
AxisVelocity axisVelocity = std::get<1>(value);
Function1(axisVelocity.first, axisVelocity.second);
} else if(variable == 2) {
Function2(std::get<0>(value));
}
}
SetVariable(1, AxisVelocity(axis, velocity));
像这样,如果类型与参数不匹配,它会在运行时抛出异常(来自
std::get
)。
这当然可以进一步细化,例如通过围绕
std::variant
制作一个包装类型,它也可以在相似类型之间进行隐式转换,或者具有转发到 SetVariable(variable, Args...)
的可变参数 SetVariable(variable, std::tuple<Args...>)
等。
另一种解决方案是使枚举
variable
也在编译时确定,例如:
template<int Variable, class... Args>
void SetVariable(Args&&... args) {
if constexpr(Variable == 1) {
Function1(args...);
} else if constexpr(Variable == 2) {
Function2(args...);
}
}
SetVariable<1>(axis, velocity);
if constexpr
确保未采用的分支(取决于编译时Variable
)不会被编译,因此不需要Function2(int, double)
存在。
但在这种情况下,为不同的枚举设置不同的函数可能会更好。