Earlier this week I started writing a function which needed to represent three states in the return value, two of which had an associated value. In my mind I immediately came to the following solution
type BuildAction =
    | Reset
    | LinkOneWithNext of Statement
    | LinkManyWithNext of Statement seq
A discriminated union is perfectly suited for representing this type of scenario. Unfortunately for me I was coding in C++ and not F# so I shifted gears and started on a different solution. But I quickly grew frustrated with new solution and decided to backtrack. A discriminated union is just too ideal for this scenario so why not spend fifteen minutes and see how far I could get in defining a discriminated union structure in C++.
Of course a full discriminated union in the style of F# is not possible because C++ lacks language support for pattern matching. But I was willing to live with that and other limitations as long as I could get many of the other benefits I find with discriminated unions. In particular
- Declarative Syntax
 - Typed value access without the need to cast
 - Allow mixing of flag only and flags with values
 - Customized naming of entries (no tuple style First, Second, etc ‘)
 - Instances are read only
 
After a bit of tinkering I came up with a solution (full source at end of post) which allows for the following declaration syntax
DECLARE_DISCRIMINATED_UNION(BuildAction)
    DISCRIMINATED_UNION_FLAG(BuildAction, Reset)
    DISCRIMINATED_UNION_VALUE(BuildAction, LinkOneWithNext, Statement)
    DISCRIMINATED_UNION_VALUE(BuildAction, LinkManyWithNext, vector<Statement>)
END_DISCRIMINATED_UNION()
Each declared entry in the union is provided the following methods.
- A static factory method for creating values: CreateLinkOneWithNext
 - A method to test to see if an instance is the value type: IsLinkOneWithNext
 - A method to get the value associated with the associated value: GetLinkOneWithNext
 
    auto action = BuildAction::CreateLinkOneWithNext(statement);
    if (action.IsLinkOneWithNext()) {
        Method(action.GetLinkOneWithNext());
    }
It’s certainly far from perfect. But it did give me the tools to implement the solution in the way I inherently thought about it and freed me to spend my thinking time on other problems.
EDIT
A couple of people asked why I didn’t use boost::variant for this solution? Ideally this is the approach I would’ve taken. But for this particular scenario boost was unfortunately not an option (no weird management issues, just a boring production environment one).
Additionally the spirit of this post and experiment was just having a bit of fun and sharing the results (even though it does contain a few pieces of evil code).
DiscriminatedUnion.h
//----------------------------------------------------------------------------
//
// Discriminated Union in C++.
//
//----------------------------------------------------------------------------
#ifdef DECLARE_DISCRIMINATED_UNION
#undef DECLARE_DISCRIMINATED_UNION
#endif
#ifdef END_DISCRIMINATED_UNION
#undef END_DISCRIMINATED_UNION
#endif
#ifdef DISCRIMINATED_UNION_VALUE
#undef DISCRIMINATED_UNION_VALUE
#endif
#ifdef DISCRIMINATED_UNION_POINTER
#undef DISCRIMINATED_UNION_POINTER
#endif
#ifdef DISCRIMINATED_UNION_ALLOW_NONE
#undef DISCRIMINATED_UNION_ALLOW_NONE
#endif
#ifdef DISCRIMINATED_UNION_GET_KIND
#undef DISCRIMINATED_UNION_GET_KIND
#endif
#define DECLARE_DISCRIMINATED_UNION(name)       \
    struct name {                               \
    private:                                    \
        name() {}                               \
        unsigned __int32 m_kind;                \
    public:
#define DECLARE_DISCRIMINATED_UNION_WITH_NONE(name)         \
    struct name {                                           \
    private:                                                \
        unsigned __int32 m_kind;                            \
    public:                                                 \
        name() : m_kind(__LINE__) {}                        \
        bool IsNone() const {return m_kind == __LINE__;}
#define DISCRIMINATED_UNION_VALUE(unionName, entryName, entryType)                                          \
        static unionName Create##entryName(const entryType& value) {                                        \
            unionName unionValue;                                                                           \
            unionValue.m_kind = __LINE__;                                                                   \
            unionValue.m_##entryName = value;                                                               \
            return unionValue;  }                                                                           \
        bool Is##entryName() const { return m_kind == __LINE__;}                                            \
        const entryType& Get##entryName() const { ASSERT(m_kind == __LINE__); return m_##entryName; }       \
        entryType Get##entryName() { ASSERT(m_kind == __LINE__); return m_##entryName; }                    \
    private:                                                                                                \
        entryType m_##entryName;                                                                            \
    public:
#define DISCRIMINATED_UNION_POINTER(unionName, entryName, entryType)                                        \
        static unionName Create##entryName(entryType* value) {                                              \
            unionName unionValue;                                                                           \
            unionValue.m_kind = __LINE__;                                                                   \
            unionValue.m_##entryName = value;                                                               \
            return unionValue;  }                                                                           \
        bool Is##entryName() const { return m_kind == __LINE__;}                                            \
        entryType* Get##entryName() const { ASSERT(m_kind == __LINE__); return m_##entryName; }             \
        entryType* Get##entryName() { ASSERT(m_kind == __LINE__); return m_##entryName; }                   \
    private:                                                                                                \
        entryType* m_##entryName;                                                                           \
    public:
#define DISCRIMINATED_UNION_FLAG(unionName, entryName)                                                      \
        static unionName Create##entryName() {                                                              \
            unionName unionValue;                                                                           \
            unionValue.m_kind = __LINE__;                                                                   \
            return unionValue;  }                                                                           \
        bool Is##entryName() const { return m_kind == __LINE__;}                                            
#define DISCRIMINATED_UNION_GET_KIND() unsigned __int32 GetKind() const { return m_kind; }
#define END_DISCRIMINATED_UNION() };