I'm not sure a recursive definition makes sense in this case. It allows arbitrarily many nested vectors inside a single ScriptParameter
. (Essentially we're saying that a script parameter is either a single value or an entire forest of values.) Splitting the definition in two might work better:
// Represents the value of a single parameter passed to a script
using ScriptParameter = std::variant<bool, int, double, std::string>;
// Represents a collection of one or many script parameters
using ScriptParameterSet = std::variant<ScriptParameter, std::vector<ScriptParameter>>;
Alternatively, if the goal here is to define a parameter as one of a set of choices plus a vector of those same choices, you could try a little template magic:
template <class T, class U> struct variant_concat;
template <class... T, class U> struct variant_concat<std::variant<T...>, U>
{
using type = std::variant<T..., U>;
};
template <class T, class U> using variant_concat_t = typename variant_concat<T, U>::type;
using PrimitiveScriptParameter = std::variant<bool, int, double, std::string>;
using ScriptParameter = variant_concat_t<
PrimitiveScriptParameter,
std::vector<PrimitiveScriptParameter>>;
This should address Lightness's usability concern below.
ScriptParameter
as? The type, or the forward declared class? – Cuneate