What's a good pattern to calculate a variable only when it is used the first time? [closed]
Solution 1:
Whereas std::string
has empty value which might mean "not computed", you might use more generally std::optional
which handle empty string and non default constructible types:
void PrintToGameMasters()
{
std::optional<std::string> message;
for (Player* player : GetAllPlayers()) {
if (player->IsGameMaster()) {
if (!message) {
message = GetComplicatedDebugMessage();
}
player->SendMessage(*message);
}
}
}
Solution 2:
Use data-oriented design; keep two lists of players: game masters and non-game masters (or all players like you have now + a separate vector of pointers to game-masters only).
void PrintToGameMasters()
{
auto players = GetGameMasters(); // Returns ONLY game master players
if (players.begin() != players.end()) {
std::string message = GetComplicatedDebugMessage();
for (Player* player : players) {
player->SendMessage(message);
}
}
}
The goal is to minimize if
-statements inside loops.
Optimize for the most common case, not the most generic one; the most common case is that a player is not a game master; so avoid looping over them.
P.S. Since you're developing a game, I want to add this link to Mike Acton's cppcon talk which you might find interesting.
Solution 3:
Some good ideas here, but I like to keep it a bit more simple:
void PrintToGameMasters()
{
std::string message;
for (Player* player : GetAllPlayers())
{
if (player->IsGameMaster())
{
if (message.empty())
message = GetComplicatedDebugMessage();
player->SendMessage(message);
}
}
}
Everybody can follow this, and it's cheap as chips… plus it's easy as pie to debug.
Solution 4:
You can use std::call_once
with a lambda to call the function the first time you find a game master like
void PrintToGameMasters()
{
std::once_flag of;
std::string message;
for (Player* player : GetAllPlayers())
if (player->IsGameMaster())
{
std::call_once(of, [&](){ message = GetComplicatedDebugMessage(); });
player->SendMessage(message);
}
}