text: /* Distributed under the Apache License, Version 2.0.
     See accompanying NOTICE file for details.*/
  
  #pragma once
  
  #include <iostream>
  #include <sstream>
  #include <string>
  #include <algorithm>
  #include <vector>
  #include <iterator>
  
  // Not sure why I have such a facination with enums, but..
  // This is a bit of a pet project, I have been curious to see how one can make
  // and enum that both, has string mappings and is iterable
  // It would really be nice to have unbound wildcard templates in C++ some how...
  // I really want to be able to have a compartment manager be populated with
  // a set of compartments defined in a custom enum definition
  // and have the compartment manager getCompartment method take in the custom type
  // And allow for support of multiple custom types.. 
  // At anyrate, I am only using this in unit testing
  // Found these articles that helped come up with this junk
  // http://www.cprogramming.com/c++11/c++11-nullptr-strongly-typed-enum-class.html
  // http://www.cprogramming.com/tutorial/template_specialization.html
  // http://codereview.stackexchange.com/questions/57626/iterable-enum-class-in-c11
  // http://codereview.stackexchange.com/questions/14309/conversion-between-enum-and-string-in-c-class-header?rq=1
  // http://stackoverflow.com/questions/6288812/template-in-c
  
  // This is the type that will hold all the strings.
  // Each enumerate type will declare its own specialization.
  // Any enum that does not have a specialization will generate a compiler error
  // indicating that there is no definition of this variable (as there should be
  // be no definition of a generic version).
  template<typename T>
  struct enumStrings
  {
    static char const* values[];
  };
  
  // Here is a base class that works via an index and string
  struct SmartEnum
  {
    virtual int index() const = 0;
    virtual const std::string& string() const = 0;
  };
  
  // Here are is a macro to fill out the contents of a SmartEnum struct
  // You only need to provide the struct, the enum associated (and how many)
  // and the strings mapped to those enums
  
  #define SMART_ENUM(Clazz, Type, Length) \
   static constexpr std::size_t _size = Length; \
  \
    Clazz() : _idx(0) {} \
    Clazz(Type t) { _idx = static_cast<Type>(t); } \
    virtual ~Clazz() {} \
  \
    int index() const { return _idx; } \
    const Type value() const { return Type(_idx); } \
    const char* string() const { return Clazz::Value(_idx); } \
    void set(const Type& t) { _idx = static_cast<int>(t); } \
  \
    Type        operator++() { if (_idx != (_size - 1)) _idx++;  return Type(_idx); } \
    Type        operator++(int) { if (_idx != (_size - 1)) _idx++;  return Type(_idx); } \
    bool        operator==(Clazz const& rhs) { return _idx == rhs._idx; } \
    bool        operator!=(Clazz const& rhs) { return _idx != rhs._idx; } \
  protected: \
    int    _idx; \
  public:   
  
  // Here is an example (You don't need to derive from SmartEnum if you don't want to)
  //struct ExampleEnum : public SmartEnum
  //{
  //  // NOTE, THESE ENUMS MUST BE OF THE DEFAULT INDEXING (You can't say enum Type {A=10, B=30 }
  //  enum Type { A, B, C };
  //  SMART_ENUM(ExampleEnum, Type, 3);
  //  static char const* Value(size_t idx);
  //};// Length of enum and values[] must be the same, and reflected in the input to SMART_ENUM
  // Put this in your cpp file
  //template<> char const* enumStrings<ExampleEnum>::values[] = { "Alpha", "Bravo", "Charlie" };
  //char const* ExampleEnum::Value(size_t idx)
  //{
  //  return enumStrings<ExampleEnum>::values[idx];
  //}
  //NOTE: You can also templitize this class with the enum type if you want, but how to you set the size?
  //I will figure that out when/if I need it
  
  