Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good pattern to calculate a variable only when it is used the first time? [closed]

Tags:

c++

Not an actual problem but I'm looking for a pattern to improve the following logic:

void PrintToGameMasters() {     std::string message = GetComplicatedDebugMessage(); // This will create a big string with various info     for (Player* player : GetAllPlayers())        if (player->IsGameMaster())            player->SendMessage(message); } 

This code works, but the issue I have is that in most cases there aren't any gamemasters players so the message composition will be done for nothing.

I'd like to write something that would only create the message on the first use of that variable, but I can't come up with a good solution here.

EDIT: To make this question more precise, I'm looking for a solution that's not specific to strings, it could be a type without a function to test if it's initialized. Also big bonus points if we can keep the call to GetComplicatedDebugMessage at the top of the loop, I think a solution involving a wrapper would solve this.

like image 566
Kelno Avatar asked Aug 15 '19 13:08

Kelno


2 Answers

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);        }     } } 
like image 184
Jarod42 Avatar answered Sep 21 '22 18:09

Jarod42


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.

like image 42
rustyx Avatar answered Sep 20 '22 18:09

rustyx