A small merge function applies an override while keeping the default config intact.

base config Start with a known base configuration so missing overrides still have useful values.
override Apply an override only when it is present and valid for the project rule.

Config Merge

overrideTimeout
config_merge.cpp
Replay: real traced execution (multi-file project)
#include <iostream>

struct Config {
    int retries;
    int timeout;
};

Config mergeConfig(Config base, int overrideTimeout) {
    if (overrideTimeout > 0) {
        base.timeout = overrideTimeout;
    }
    return base;
}

int main() {
    int overrideTimeout = 15;

    Config base{3, 30};
    Config active = mergeConfig(base, overrideTimeout);
    int waitBudget = active.retries * active.timeout;

    std::cout << "timeout=" << active.timeout << std::endl;
    std::cout << "waitBudget=" << waitBudget << std::endl;
    return 0;
}
#include <iostream>

struct Config {
    int retries;
    int timeout;
};

Config mergeConfig(Config base, int overrideTimeout) {
    if (overrideTimeout > 0) {
        base.timeout = overrideTimeout;
    }
    return base;
}

int main() {
    int overrideTimeout = 0;

    Config base{3, 30};
    Config active = mergeConfig(base, overrideTimeout);
    int waitBudget = active.retries * active.timeout;

    std::cout << "timeout=" << active.timeout << std::endl;
    std::cout << "waitBudget=" << waitBudget << std::endl;
    return 0;
}
#include <iostream>

struct Config {
    int retries;
    int timeout;
};

Config mergeConfig(Config base, int overrideTimeout) {
    if (overrideTimeout > 0) {
        base.timeout = overrideTimeout;
    }
    return base;
}

int main() {
    int overrideTimeout = 45;

    Config base{3, 30};
    Config active = mergeConfig(base, overrideTimeout);
    int waitBudget = active.retries * active.timeout;

    std::cout << "timeout=" << active.timeout << std::endl;
    std::cout << "waitBudget=" << waitBudget << std::endl;
    return 0;
}
  1. overrideTimeout ← 15, base ← (empty)

    15int main() {16    int overrideTimeout→ 15 = 15; //@overrideTimeout=0, 451718    Config base→ (empty){3, 30};19    Config active = mergeConfig(base(empty), overrideTimeout15);20    int waitBudget = active.retries * active.timeout;
  2. Config mergeConfig(Config base, int overrideTimeout)

    8Config mergeConfig(Config base(empty), int overrideTimeout15) {9    if (overrideTimeout > 0) {
  3. base.timeout ← 15

    8Config mergeConfig(Config base, int overrideTimeout) {9    if (overrideTimeout15 > 0) {10        base.timeout→ 15 = overrideTimeout15;11    }
  4. return base;

    11    }12    return base(empty);13}
  5. active ← (empty), waitBudget ← 45

    18    Config base{3, 30};19    Config active→ (empty) = mergeConfig(base(empty), overrideTimeout15);20    int waitBudget→ 45 = active.retries3 * active.timeout15;2122    std::cout << "timeout=" << active(empty).timeout << std::endl;23    std::cout << "waitBudget=" << waitBudget45 << std::endl;24    return 0;25}
    outputtimeout=15
    waitBudget=45
  1. overrideTimeout ← 0, base ← (empty)

    15int main() {16    int overrideTimeout→ 0 = 0;1718    Config base→ (empty){3, 30};19    Config active = mergeConfig(base(empty), overrideTimeout0);20    int waitBudget = active.retries * active.timeout;
  2. Config mergeConfig(Config base, int overrideTimeout)

    8Config mergeConfig(Config base(empty), int overrideTimeout0) {9    if (overrideTimeout > 0) {10        base.timeout = overrideTimeout;11    }12    return base(empty);13}
  3. active ← (empty), waitBudget ← 90

    18    Config base{3, 30};19    Config active→ (empty) = mergeConfig(base(empty), overrideTimeout0);20    int waitBudget→ 90 = active.retries3 * active.timeout30;2122    std::cout << "timeout=" << active(empty).timeout << std::endl;23    std::cout << "waitBudget=" << waitBudget90 << std::endl;24    return 0;25}
    outputtimeout=30
    waitBudget=90
  1. overrideTimeout ← 45, base ← (empty)

    15int main() {16    int overrideTimeout→ 45 = 45;1718    Config base→ (empty){3, 30};19    Config active = mergeConfig(base(empty), overrideTimeout45);20    int waitBudget = active.retries * active.timeout;
  2. Config mergeConfig(Config base, int overrideTimeout)

    8Config mergeConfig(Config base(empty), int overrideTimeout45) {9    if (overrideTimeout > 0) {
  3. base.timeout ← 45

    8Config mergeConfig(Config base, int overrideTimeout) {9    if (overrideTimeout45 > 0) {10        base.timeout→ 45 = overrideTimeout45;11    }
  4. return base;

    11    }12    return base(empty);13}
  5. active ← (empty), waitBudget ← 135

    18    Config base{3, 30};19    Config active→ (empty) = mergeConfig(base(empty), overrideTimeout45);20    int waitBudget→ 135 = active.retries3 * active.timeout45;2122    std::cout << "timeout=" << active(empty).timeout << std::endl;23    std::cout << "waitBudget=" << waitBudget135 << std::endl;24    return 0;25}
    outputtimeout=45
    waitBudget=135