gpt4 book ai didi

c++ - 两个其他方面相同的功能(一个使用模板模式,另一个不使用)

转载 作者:行者123 更新时间:2023-11-30 02:41:56 25 4
gpt4 key购买 nike

#include <iostream>

void doSomething (int x) {std::cout << "Do something with " << x << std::endl;}

struct Base {
virtual int foo() const {return 5;}
virtual int goo() const {return 6;}
virtual int hoo() const {return 7;}
void noTemplatePattern() const {
// Code A
if (Base::foo() < 6) {
// Code B
}
doSomething (Base::goo());
// Code C
if (Base::hoo() > 10) {
// Code D
}
}
void templatePattern() const {
// Code A
if (foo() < 6) {
// Code B
}
doSomething (goo());
// Code C
if (hoo() > 10) {
// Code D
}
}
};

struct Derived : Base {
virtual int foo() const override {return 12;}
virtual int goo() const override {return 13;}
virtual int hoo() const override {return 14;}
};

int main() {
Derived d;
d.noTemplatePattern();
d.templatePattern();
}

除了为每个代码创建辅助函数之外,如何最好地避免重复代码 A、代码 B、代码 C、代码 D 等中包含的代码?有更通用的方法吗?除了一个使用模板模式而另一个不使用之外,我有一些相同的功能。虚函数之间的代码体是相同的。如果我为每个相同的部分定义一个辅助函数,它会变得非常困惑,而且它们也会太多。

如果您想了解更多,这里是我的生产代码片段,说明了这一点。 SpellCaster源自 LivingBeing , 和 LivingBeing::cannotAttackLongRange(int)SpellCaster::cannotAttackLongRange(int) 覆盖.

inline std::set<LivingBeingProxy*> LivingBeing::unattackableTargets() const {
std::set<LivingBeingProxy*> nonTargets;
if (isCharmed()) {
for (auto it = std::next(getStatesList(CHARM_SPELL).begin(), 1); it != getStatesList(CHARM_SPELL).end(); ++it)
nonTargets.emplace (std::dynamic_pointer_cast<CharmedStateBase>(*it)->getCharmer());
}
for (LivingBeingProxy* x : getLocation()->allBeingsAlive()) {
if ( (x->heightAboveGround() > damageInflictor(0)->getReach()) && !canFly()
&& LivingBeing::cannotAttackLongRange(distanceBetween(this, x->getActual()))) //*** virtual method here!
{nonTargets.emplace(x); continue;}
if ( (x->heightAboveGround()) < 0 && (x->getTerrain() == InWater) && !canSwim() )
{nonTargets.emplace(x); continue;}
}
// ...
return nonTargets;
}

inline std::set<LivingBeingProxy*> LivingBeing::unattackableTargetsIncludingBySpells() const {
std::set<LivingBeingProxy*> nonTargets;
if (isCharmed()) {
for (auto it = std::next(getStatesList(CHARM_SPELL).begin(), 1); it != getStatesList(CHARM_SPELL).end(); ++it)
nonTargets.emplace (std::dynamic_pointer_cast<CharmedStateBase>(*it)->getCharmer());
}
for (LivingBeingProxy* x : getLocation()->allBeingsAlive()) {
if ( (x->heightAboveGround() > damageInflictor(0)->getReach()) && !canFly()
&& cannotAttackLongRange (distanceBetween(this, x->getActual()))) //*** virtual method here!
{nonTargets.emplace(x); continue;}
if ( (x->heightAboveGround()) < 0 && (x->getTerrain() == InWater) && !canSwim() )
{nonTargets.emplace(x); continue;}
}
// ...
return nonTargets;
}

LivingBeing::unattackableTargets()计算所有普通武器无法攻击的敌人,同时 LivingBeing::unattackableTargetsIncludingBySpells()计算所有普通武器和法术无法攻击的敌人。 SpellCaster用普通武器攻击时会想调用第一个,用法术攻击时会想调用第二个。

最佳答案

使用模板和 CRTP,如果合适的话,你可以这样做:

template <typename T, typename D>
void helper(const D& base)
{
// Code A
if (base.T::foo() < 6) {
// Code B
}
doSomething (base.T::goo());
// Code C
if (base.T::hoo() > 10) {
// Code D
}
}

struct Base {
virtual ~Base() = default;
virtual int foo() const {return 5;}
virtual int goo() const {return 6;}
virtual int hoo() const {return 7;}

void noTemplatePattern() const
{
// use Base::foo, Base::goo and Base::hoo
helper<Base>(*this);
}
#if 0
virtual void templatePattern() const = 0;
#endif
};

template <typename Derived>
struct BaseImpl : Base {
template <typename Derived>
void BaseImpl<Derived>::templatePattern() const {
// use Derived::foo, Derived::goo and Derived::hoo
helper<Derived>(static_cast<const Derived&>(*this));
}
};

Live example

关于c++ - 两个其他方面相同的功能(一个使用模板模式,另一个不使用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27593518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com