I'm using a variant to store a range of types for a syntax parser in C++. Each constituent of a syntax rule has a category (of type enum) and a value. The constituent stores a type of value according to the category. For the sake of example I've simplified the categories to 'String' => stores a string, and 'Number' => stores an int.

I would like to get the value of the constituent with the correct type according to its category enum. How can I do this?

I've written example code below, where I construct two constituents: strCon, storing a string, and intCon, storing an int, and attempt to get their values.

I want to assign the string in strCon into strVal,
and the int from intCon into intVal.

```cpp
#include <variant>

struct Constituent
{
    enum class Category {String, Number};
    using Value = std::variant<std::string, int>;

    Category cat;
    Value val;

    // Using a struct ideally to allow partial specialisation of the template,
    // so I can pass the enum without the return type.
    template<Category T>
    struct OfCategory {};

    template<Category T, typename U>
    friend U const& getValue(OfCategory<T>, Constituent const&);
}

using Category = Constituent::Category;

// Template to return the value as the correct type
// for the constituent's category.
template<Category T, typename U>
U const& getValue(OfCategory<T> type, Constituent const& constituent)
{
    // Uses the variant's get function.
    return std::get<U>(constituent.val);
}

// Specialisation to return string from Category::String.
template<>
string const& getValue(OfCategory<Category::String> type,
    Constituent const& constituent)
{
    return getValue<Category::String, string>(constituent);
}

// Specialisation to return int from Category::Number.
template<>
int const& getValue(OfCategory<Category::Number> type,
    Constituent const& constituent)
{
    return getValue<Category::Number, int>(constituent);
}

int main()
{
    Constituent strCon = {Category::String, "This is a string!"};
    Constituent intCon = {Category::Number, 20};

    // In my current implementation, I want this to work with
    // the type wrapper as an overload for the function.
    string strVal = getValue(OfCategory<Category::String>{}, strCon);
    int intVal = getValue(OfCategory<Category::Number>{}, intCon);

    // But it would be better to directly use the template.
    strVal = getValue<Category::String>(strCon);
    intVal = getValue<Category::Number>(intCon);

    // The only way I can get it to work, is to explicitly provide
    // the return type, which defeats the point.
    strVal = getValue<Category::String, string>(
        OfCategory<Category::String>{}, strCon);
    intVal = getValue<Category::Number, int>(
        OfCategory<Category::Number>{}, intCon);

    // Ideally, I could use the cat parameter in Constituent to dynamically
    // infer the return type, but I don't believe something like this is
    // possible in C++.
}

```