使用参数包和元组创建简单表达式 class
Creating a simple expression class with parameter packs and tuples
我正在尝试创建一个表达式 class,它采用从 "DMGType" 派生的 classes 并将它们相加,例如:
CritDamage+4*AllDamage+MeleeDamage
然后使用 "build" 参数计算其值,例如如果构建在编程术语中为 "Mage" = 0,则结果应为:
CritDamage(0)+4*AllDamage(0)+MeleeDamage(0) = 0.5+4*1+0
这是我的尝试:
#include<iostream>
#include<tuple>
#include<cstddef>
template <typename ValueType>
class DMGType {
public:
ValueType coeff=0;
virtual ValueType getExpo(std::size_t build) = 0;
DMGType<ValueType>& sum(DMGType<ValueType> const& dmg) {
this->coeff+=dmg.coeff;
return this;
}
};
template<typename ValueType, class... DMGTypesDerived>
class Expression {
public:
std::tuple<DMGTypesDerived...> parameters;
void sum(DMGType<ValueType> const& dmg) {
std::get<dmg>(parameters).sum(dmg);
}
ValueType result{0};
//desired result: return std::get<DMGTypes1>(parameters).getExpo(build) + ... + std::get<DMGTypesLast>.getExpo(build);
result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
return result;
};
class CritDamage: public DMGType<double> {
public:
double getExpo(std::size_t build) {
return build+1;
}
};
int main() {
Expression<double, CritDamage> test;
CritDamage crit;
crit.coeff=1;
test.sum(crit);
std::cout<<test.getExpo(0);
}
我遇到的错误:
prog.cc:24:69: error: expected ';' before '+' token
24 | result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
| ^~
| ;
prog.cc:24:15: error: parameter packs not expanded with '...':
24 | result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
prog.cc:24:15: note: 'DMGTypesDerived'
我对 lambda 函数、std::apply、调用、转发 expansion/folding 持开放态度,但到目前为止我尝试的所有操作都给了我一些错误,因为我不完全理解这些概念。
我也知道无法处理多态性的 Expression::sum 函数会出现问题,我也非常感谢您在这方面的帮助。
解决方案
#include<iostream>
#include<tuple>
#include<cstddef>
template <typename ValueType>
class DMGType {
public:
DMGType(ValueType v)
:coeff(v) {};
DMGType()
:coeff(0) {};
ValueType coeff=0;
virtual ValueType getExpo(std::size_t build) = 0;
void sum(DMGType<ValueType> const& dmg) {
this->coeff+=dmg.coeff;
}
};
template<typename ValueType, class... DMGTypesDerived>
class Expression {
public:
std::tuple<DMGTypesDerived...> parameters;
template<class DerivedClass>
void sum(DerivedClass const& dmg) {
std::get<DerivedClass>(parameters).sum(dmg);
}
ValueType getExpo(std::size_t build) {
return (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
}
};
class CritDamage: public DMGType<double> {
public:
double coeff=0;
CritDamage(double v) :coeff(v) {}
CritDamage() :coeff(0) {}
double getExpo(std::size_t build) {
return build+1;
}
};
class MeleeDamage: public DMGType<double> {
public:
double coeff=0;
MeleeDamage(double v) :coeff(v) {}
MeleeDamage() :coeff(0) {}
double getExpo(std::size_t build) {
return build*2+1;
}
};
int main() {
Expression<double, CritDamage, MeleeDamage> test;
CritDamage crit(1);
test.sum(crit);
MeleeDamage melee(2);
melee.sum(crit);
std::cout<<test.getExpo(1);
}
您可以即时创建初始化列表并对结果求和:
ValueType getExpo(std::size_t build) {
ValueType result{0};
//desired result: return std::get<DMGTypes1>(parameters).getExpo(build) + ... + std::get<DMGTypesLast>.getExpo(build);
for (auto s : { std::get<DMGTypesDerived>(parameters).getExpo(build)...} )
result += s;
return result;
}
您在折叠表达式中遗漏了一些括号。试试这个:
ValueType getExpo(std::size_t build) {
ValueType result{0};
result += (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
return result;
}
事实上,您可以跳过 result
并直接执行此操作:
ValueType getExpo(std::size_t build) {
return (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
}
我正在尝试创建一个表达式 class,它采用从 "DMGType" 派生的 classes 并将它们相加,例如:
CritDamage+4*AllDamage+MeleeDamage
然后使用 "build" 参数计算其值,例如如果构建在编程术语中为 "Mage" = 0,则结果应为:
CritDamage(0)+4*AllDamage(0)+MeleeDamage(0) = 0.5+4*1+0
这是我的尝试:
#include<iostream>
#include<tuple>
#include<cstddef>
template <typename ValueType>
class DMGType {
public:
ValueType coeff=0;
virtual ValueType getExpo(std::size_t build) = 0;
DMGType<ValueType>& sum(DMGType<ValueType> const& dmg) {
this->coeff+=dmg.coeff;
return this;
}
};
template<typename ValueType, class... DMGTypesDerived>
class Expression {
public:
std::tuple<DMGTypesDerived...> parameters;
void sum(DMGType<ValueType> const& dmg) {
std::get<dmg>(parameters).sum(dmg);
}
ValueType result{0};
//desired result: return std::get<DMGTypes1>(parameters).getExpo(build) + ... + std::get<DMGTypesLast>.getExpo(build);
result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
return result;
};
class CritDamage: public DMGType<double> {
public:
double getExpo(std::size_t build) {
return build+1;
}
};
int main() {
Expression<double, CritDamage> test;
CritDamage crit;
crit.coeff=1;
test.sum(crit);
std::cout<<test.getExpo(0);
}
我遇到的错误:
prog.cc:24:69: error: expected ';' before '+' token
24 | result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
| ^~
| ;
prog.cc:24:15: error: parameter packs not expanded with '...':
24 | result+=std::get<DMGTypesDerived>(parameters).getExpo(build) + ...;
prog.cc:24:15: note: 'DMGTypesDerived'
我对 lambda 函数、std::apply、调用、转发 expansion/folding 持开放态度,但到目前为止我尝试的所有操作都给了我一些错误,因为我不完全理解这些概念。
我也知道无法处理多态性的 Expression::sum 函数会出现问题,我也非常感谢您在这方面的帮助。
解决方案
#include<iostream>
#include<tuple>
#include<cstddef>
template <typename ValueType>
class DMGType {
public:
DMGType(ValueType v)
:coeff(v) {};
DMGType()
:coeff(0) {};
ValueType coeff=0;
virtual ValueType getExpo(std::size_t build) = 0;
void sum(DMGType<ValueType> const& dmg) {
this->coeff+=dmg.coeff;
}
};
template<typename ValueType, class... DMGTypesDerived>
class Expression {
public:
std::tuple<DMGTypesDerived...> parameters;
template<class DerivedClass>
void sum(DerivedClass const& dmg) {
std::get<DerivedClass>(parameters).sum(dmg);
}
ValueType getExpo(std::size_t build) {
return (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
}
};
class CritDamage: public DMGType<double> {
public:
double coeff=0;
CritDamage(double v) :coeff(v) {}
CritDamage() :coeff(0) {}
double getExpo(std::size_t build) {
return build+1;
}
};
class MeleeDamage: public DMGType<double> {
public:
double coeff=0;
MeleeDamage(double v) :coeff(v) {}
MeleeDamage() :coeff(0) {}
double getExpo(std::size_t build) {
return build*2+1;
}
};
int main() {
Expression<double, CritDamage, MeleeDamage> test;
CritDamage crit(1);
test.sum(crit);
MeleeDamage melee(2);
melee.sum(crit);
std::cout<<test.getExpo(1);
}
您可以即时创建初始化列表并对结果求和:
ValueType getExpo(std::size_t build) {
ValueType result{0};
//desired result: return std::get<DMGTypes1>(parameters).getExpo(build) + ... + std::get<DMGTypesLast>.getExpo(build);
for (auto s : { std::get<DMGTypesDerived>(parameters).getExpo(build)...} )
result += s;
return result;
}
您在折叠表达式中遗漏了一些括号。试试这个:
ValueType getExpo(std::size_t build) {
ValueType result{0};
result += (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
return result;
}
事实上,您可以跳过 result
并直接执行此操作:
ValueType getExpo(std::size_t build) {
return (std::get<DMGTypesDerived>(parameters).getExpo(build) + ...);
}