terminal/src/inc/til/coalesce.h
Carlos Zamora b603929214
Make Global and Profile settings inheritable (#7923)
## Summary of the Pull Request
Introduces `IInheritable` as an interface that helps move cascading settings into the Terminal Settings Model. `GlobalAppSettings` and `Profile` both are now `IInheritable`. `CascadiaSettings` was updated to `CreateChild()` for globals and each profile when we are loading the JSON data.

IInheritable does most of the heavy lifting. It introduces a two new macros and the interface. The macros help implement the fallback functionality for nullable and non-nullable settings.

## References
#7876 - Spec Addendum
#6904 - TSM Spec
#1564 - Settings UI

#7876 - `Copy()` needs to be updated to include _parent
2020-10-27 17:35:09 +00:00

61 lines
2.1 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace til
{
// Method Description:
// - Base case provided to handle the last argument to coalesce_value<T...>()
template<typename T>
T coalesce_value(const T& base)
{
return base;
}
// Method Description:
// - Base case provided to throw an assertion if you call coalesce_value(opt, opt, opt)
template<typename T>
T coalesce_value(const std::optional<T>& base)
{
static_assert(false, "coalesce_value must be passed a base non-optional value to be used if all optionals are empty");
return T{};
}
// Method Description:
// - Returns the value from the first populated optional, or a base value if none were populated.
template<typename T, typename... Ts>
T coalesce_value(const std::optional<T>& t1, Ts&&... t2)
{
// Initially, I wanted to check "has_value" and short-circuit out so that we didn't
// evaluate value_or for every single optional, but has_value/value emits exception handling
// code that value_or doesn't. Less exception handling is cheaper than calling value_or a
// few more times.
return t1.value_or(coalesce_value(std::forward<Ts>(t2)...));
}
// Method Description:
// - Base case provided to handle the last argument to coalesce_value<T...>()
template<typename T>
std::optional<T> coalesce(const std::optional<T>& base)
{
return base;
}
// Method Description:
// - Base case provided to handle the last argument to coalesce_value<T...>(..., nullopt)
template<typename T>
std::optional<T> coalesce(const std::nullopt_t& base)
{
return base;
}
// Method Description:
// - Returns the value from the first populated optional, or the last one (if none of the previous had a value)
template<typename T, typename... Ts>
std::optional<T> coalesce(const std::optional<T>& t1, Ts&&... t2)
{
return t1.has_value() ? t1 : coalesce(std::forward<Ts>(t2)...);
}
}