I'm using C++0x's lambdas to define boost functions. I have some classes where I define some of their behaviour using lambdas/boost functions. What I was wondering is, is it possible to expose data about the classes into the lambda's context without altering the function definition? For example, I have a set of class like this:
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;
}
And inside the constructor for stat boosting item, I'd like to be able to do this:
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
}
}
};
}
This is more a curiosity thing as I know I can simply extend the boost::function definition to include a pointer to the item in question and get the data that way, or override my Use functions. But if I could somehow expose information into lambda about the class that contains it, that would be ideal as I'd be able to make use of it elsewhere as well
Do you need to access variables that are available in the scope of StatBoostingItem::StatBoostingItem from your lambda? In that case you could simply use captures:
RegularUse = [&](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)
The [&] tells the lambda to captures everything from the current scope by reference. If you need just a specific variable, you can capture just it, and you could also use [=] to capture everything by value. I guess you can also use [this] to capture a pointer to the Item instance:
RegularUse = [this](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)
Didn't ever try that, but I see no reason why it shouldn't work. If it doesn't work (because this
is somehow reserved, even though lambdas aren't methods), you can always work around it by assigning this
to another variable and capturing it instead:
Item* item = this;
RegularUse = [item](std::set<Character::BaseCharacter*> users, std::set<Character::BaseCharacter*> targets)
{
item.DoSomething();
}