A Thought Experiment: Simplifying C++ Function Calls with Structs (C++20)

Ever dealt with a C++ function that has too many parameters, most of which are optional? Here’s an example:

auto llm(
    ChatCompletionsQuery,
    int npredict = 2048,
    float temperature = 1.f,
    std::vector<std::string> stopTokens = {}
) -> std::string;

In this case, ChatCompletionsQuery is essential, but the other parameters often use their defaults. If you just want to tweak temperature, the call can get unwieldy.

So, here’s a thought: what if we refactored to group these optional parameters into a struct? With C++20’s designated initializers, you can do this easily:

struct LlmIn {
    int npredict = 2048;
    float temperature = 1.f;
    std::vector<std::string> stopTokens = {};
};

auto llm(const ChatCompletionsQuery& query, const LlmIn& options = {}) -> std::string;

Now, you can adjust only what you need:

llm(query, {.temperature = 2.f});

Why This Might Work

  1. Cleaner Calls: Override only the parameters you need, keeping calls concise.
  2. Future-Friendly: If more options get added, they just go in the struct.
  3. One-Stop Defaults: Set all defaults in one place for easy updates.

I haven’t tried this yet, but it seems like a clean way to keep code readable and flexible—if you’re working with C++20 or later. Worth a try?

Previous