Settings in cppfig are defined as structs with specific static members. This design enables compile-time type safety and IDE autocompletion.
Every setting must have these three members:
struct MySetting {
// Path in the config file (dot-separated for hierarchy)
static constexpr std::string_view path = "category.subcategory.name";
// The value type
using value_type = int;
// Default value factory function
static auto default_value() -> int { return 42; }
};Allow the setting to be overridden via environment variable:
struct ServerHost {
static constexpr std::string_view path = "server.host";
static constexpr std::string_view env_override = "SERVER_HOST"; // Optional
using value_type = std::string;
static auto default_value() -> std::string { return "localhost"; }
};When SERVER_HOST environment variable is set, it takes precedence over the file value.
Add validation to ensure values are within acceptable bounds:
struct ServerPort {
static constexpr std::string_view path = "server.port";
using value_type = int;
static auto default_value() -> int { return 8080; }
// Optional: Validator for this setting
static auto validator() -> cppfig::Validator<int> {
return cppfig::Range(1, 65535);
}
};Here's a comprehensive example with all features:
namespace settings {
// Simple setting
struct AppName {
static constexpr std::string_view path = "app.name";
using value_type = std::string;
static auto default_value() -> std::string { return "MyApplication"; }
};
// Setting with environment override
struct DatabaseUrl {
static constexpr std::string_view path = "database.url";
static constexpr std::string_view env_override = "DATABASE_URL";
using value_type = std::string;
static auto default_value() -> std::string {
return "postgresql://localhost:5432/mydb";
}
};
// Setting with validator
struct MaxConnections {
static constexpr std::string_view path = "database.pool.max_connections";
using value_type = int;
static auto default_value() -> int { return 10; }
static auto validator() -> cppfig::Validator<int> {
return cppfig::Range(1, 100);
}
};
// Setting with environment override AND validator
struct ServerPort {
static constexpr std::string_view path = "server.port";
static constexpr std::string_view env_override = "PORT";
using value_type = int;
static auto default_value() -> int { return 8080; }
static auto validator() -> cppfig::Validator<int> {
return cppfig::Range(1, 65535);
}
};
// Boolean setting
struct DebugMode {
static constexpr std::string_view path = "app.debug";
static constexpr std::string_view env_override = "DEBUG";
using value_type = bool;
static auto default_value() -> bool { return false; }
};
// Enum-like string setting
struct LogLevel {
static constexpr std::string_view path = "logging.level";
using value_type = std::string;
static auto default_value() -> std::string { return "info"; }
static auto validator() -> cppfig::Validator<std::string> {
return cppfig::OneOf<std::string>({"debug", "info", "warn", "error"});
}
};
} // namespace settingsOut of the box, cppfig supports:
| Type | File Representation | Environment Variable |
|---|---|---|
bool |
true / false |
true, false, 1, 0, yes, no, on, off |
int |
integer literal | Integer string |
std::int64_t |
integer literal | Integer string |
float |
decimal literal | Decimal string |
double |
decimal literal | Decimal string |
std::string |
string value | As-is |
For custom types, see Custom Types.
Use dot-separated paths to create hierarchical structure:
struct DatabaseHost {
static constexpr std::string_view path = "database.connection.host";
// ...
};
struct DatabasePort {
static constexpr std::string_view path = "database.connection.port";
// ...
};
struct DatabasePoolSize {
static constexpr std::string_view path = "database.pool.max_size";
// ...
};This generates a .conf file like:
database.connection.host = localhost
database.connection.port = 5432
database.pool.max_size = 10
Or, when using JsonSerializer:
{
"database": {
"connection": {
"host": "localhost",
"port": 5432
},
"pool": {
"max_size": 10
}
}
}When calling config.Get<MySetting>(), values are resolved in this order:
- Environment variable (if
env_overrideis defined and the env var is set) - File value (if present in the configuration file)
- Default value (from
default_value())
This means environment variables always take precedence, making it easy to override configuration in production without modifying files.