Класс внутренних лямбд и функция наддува

Я использую лямбды C++0x для определения функций наддува. У меня есть некоторые классы, где я определяю некоторые из их поведения, используя функции lambdas / boost. Что мне было интересно, так это то, можно ли выставлять данные о классах в лямбда-контекст без изменения определения функции? Например, у меня есть набор классов, как это:

class ConsumableItem : public Item
{
public:
    //Constructors here
    virtual bool Use(std::set<Character::BaseCharacter*> Users, std::set<Character::BaseCharacter*> Targets);
    virtual bool Use(std::set<Battles::BattleCharacter> Users, std::set<Battles::BattleCharacter> Targets, Battles::BattleField &field);
protected:
    bool UseRegularFunction;
    boost::function<void(std::set<Character::BaseCharacter*>, std::set<Character::BaseCharacter*>)> RegularUse;
    bool UseBattleFunction;
    boost::function<void(std::set<Battles::BattleCharacter>, std::set<Battles::BattleCharacter>, Battles::BattleField &)> BattleUse;
};

class StatBoostingItem : public ConsumableItem
{
public:
    StatBoostingItem(int UID, std::string &name, std::string &descript, boost::unordered_set<ItemFlags> Flags, boost::unordered_map<Stat, int> &boosts, int value);
protected:
    virtual bool Use(std::set<Character::BaseCharacter*> Users, std::set<Character::BaseCharacter*> Targets) override;
    virtual bool Use(std::set<Battles::BattleCharacter> Users, std::set<Battles::BattleCharacter> Targets, Battles::BattleField &field) override;
private:
    boost::unordered_map<Stat, int> StatBoosts;
}

А внутри конструктора для повышения характеристик я хотел бы сделать это:

StatBoostingItem::StatBoostingItem(int UID, std::string &name, std::string &descript, boost::unordered_set<ItemFlags> Flags, boost::unordered_map<Stat, int> &boosts, int value)
    : ConsumableItem(UID, name, descript, Flags, ItemClass::STAT_BOOSTING_ITEM, value)
{
    StatBoosts = boosts;
    RegularUse = [](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)
    {
        for (auto character = targets.begin(); character != targets.end(); ++character)
        {
            for (auto statBoost = StatBoosts.begin(); statBoost != StatBoosts.end(); ++statBoost)
            {
                //Item Effect in here
            }
        }
    };
}

Это более любопытно, так как я знаю, что могу просто расширить определение boost::function, чтобы включить указатель на рассматриваемый элемент и получить данные таким образом, или переопределить мои функции Use. Но если бы я мог каким-то образом раскрыть в лямбду информацию о классе, который ее содержит, это было бы идеально, поскольку я мог бы использовать ее и в других местах.

1 ответ

Решение

Вам нужен доступ к переменным, которые доступны в области StatBoostingItem::StatBoostingItem из вашей лямбды? В этом случае вы можете просто использовать захваты:

RegularUse = [&](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)

[&] Сообщает лямбде, что он захватывает все из текущей области по ссылке. Если вам нужна только конкретная переменная, вы можете захватить только ее, и вы также можете использовать [=] для захвата всего по значению. Я думаю, вы также можете использовать [this] для захвата указателя на экземпляр Item:

RegularUse = [this](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)

Никогда не пробовал, но я не вижу причин, почему это не должно работать. Если это не работает (потому что this как-то зарезервировано, хотя лямбды не являются методами), вы всегда можете обойти это, назначив this в другую переменную и захватывая ее вместо:

Item* item = this;
RegularUse = [item](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)
{
    item.DoSomething();
}
Другие вопросы по тегам