/**
 * Autogenerated by Thrift
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
#pragma once

#include <thrift/lib/cpp/Thrift.h>
#include <thrift/lib/cpp/TApplicationException.h>
#include <thrift/lib/cpp/protocol/TProtocol.h>
#include <thrift/lib/cpp/transport/TTransport.h>

namespace apache { namespace thrift { namespace reflection {
class Schema;
}}}




class ComplexUnion;

class ComplexUnion : public apache::thrift::TStructType<ComplexUnion> {
 public:
  enum class Type {
    __EMPTY__ = 0,
    intValue = 1,
    stringValue = 2,
    intListValue = 3,
    stringListValue = 4,
  };

  ComplexUnion() : type_(Type::__EMPTY__) {}
  ComplexUnion(const ComplexUnion& rhs) : type_(Type::__EMPTY__) {
    if (this == &rhs) { return; }
    if (rhs.type_ == Type::__EMPTY__) { return; }
    switch (rhs.type_) {
      case Type::intValue: {
        set_intValue(rhs.value_.intValue);
        break;
      }
      case Type::stringValue: {
        set_stringValue(rhs.value_.stringValue);
        break;
      }
      case Type::intListValue: {
        set_intListValue(rhs.value_.intListValue);
        break;
      }
      case Type::stringListValue: {
        set_stringListValue(rhs.value_.stringListValue);
        break;
      }
      default: assert(false);
    }
  }

  ComplexUnion& operator=(const ComplexUnion& rhs) {
    if (this == &rhs) { return *this; }
    __clear();
    if (rhs.type_ == Type::__EMPTY__) { return *this; }
    switch (rhs.type_) {
      case Type::intValue: {
        set_intValue(rhs.value_.intValue);
        break;
      }
      case Type::stringValue: {
        set_stringValue(rhs.value_.stringValue);
        break;
      }
      case Type::intListValue: {
        set_intListValue(rhs.value_.intListValue);
        break;
      }
      case Type::stringListValue: {
        set_stringListValue(rhs.value_.stringListValue);
        break;
      }
      default: assert(false);
    }
    return *this;
  }

  ComplexUnion(ComplexUnion&& rhs) : type_(Type::__EMPTY__) {
    if (this == &rhs) { return; }
    if (rhs.type_ == Type::__EMPTY__) { return; }
    switch (rhs.type_) {
      case Type::intValue: {
        set_intValue(std::move(rhs.value_.intValue));
        break;
      }
      case Type::stringValue: {
        set_stringValue(std::move(rhs.value_.stringValue));
        break;
      }
      case Type::intListValue: {
        set_intListValue(std::move(rhs.value_.intListValue));
        break;
      }
      case Type::stringListValue: {
        set_stringListValue(std::move(rhs.value_.stringListValue));
        break;
      }
      default: assert(false);
    }
    rhs.__clear();
  }

  ComplexUnion& operator=(ComplexUnion&& rhs) {
    if (this == &rhs) { return *this; }
    __clear();
    if (rhs.type_ == Type::__EMPTY__) { return *this; }
    switch (rhs.type_) {
      case Type::intValue: {
        set_intValue(std::move(rhs.value_.intValue));
        break;
      }
      case Type::stringValue: {
        set_stringValue(std::move(rhs.value_.stringValue));
        break;
      }
      case Type::intListValue: {
        set_intListValue(std::move(rhs.value_.intListValue));
        break;
      }
      case Type::stringListValue: {
        set_stringListValue(std::move(rhs.value_.stringListValue));
        break;
      }
      default: assert(false);
    }
    rhs.__clear();
    return *this;
  }


  void __clear() {
    if (type_ == Type::__EMPTY__) { return; }
    switch (type_) {
      case Type::intValue: {
        
        break;
      }
      case Type::stringValue: {
        using namespace std; value_.stringValue.~string();
        break;
      }
      case Type::intListValue: {
        using namespace std; value_.intListValue.~vector<int64_t> ();
        break;
      }
      case Type::stringListValue: {
        using namespace std; value_.stringListValue.~vector<std::string> ();
        break;
      }
      default: assert(false);
    }
    type_ = Type::__EMPTY__;
  }
  virtual ~ComplexUnion() throw() {
    __clear();
  }

  union storage_type {
    int64_t intValue;
    std::string stringValue;
    std::vector<int64_t>  intListValue;
    std::vector<std::string>  stringListValue;
    
    storage_type() {}
    ~storage_type() {}
  };

  bool operator==(const ComplexUnion& rhs) const {
    if (type_ != rhs.type_) { return false; }
    switch (type_) {
      case Type::intValue: {
        return value_.intValue == rhs.value_.intValue;

        break;
      }
      case Type::stringValue: {
        return value_.stringValue == rhs.value_.stringValue;

        break;
      }
      case Type::intListValue: {
        return value_.intListValue == rhs.value_.intListValue;

        break;
      }
      case Type::stringListValue: {
        return value_.stringListValue == rhs.value_.stringListValue;

        break;
      }
      default: return true;
    }
  }

  bool operator!=(const ComplexUnion& rhs) const {
    return !(*this == rhs);
  }

  bool operator<(const ComplexUnion& rhs) const {
    if (type_ != rhs.type_) return type_ < rhs.type_;
    switch (type_) {
      case Type::intValue: {
        return value_.intValue < rhs.value_.intValue;

        break;
      }
      case Type::stringValue: {
        return value_.stringValue < rhs.value_.stringValue;

        break;
      }
      case Type::intListValue: {
        return value_.intListValue < rhs.value_.intListValue;

        break;
      }
      case Type::stringListValue: {
        return value_.stringListValue < rhs.value_.stringListValue;

        break;
      }
      default: return false;
    }
    return false;
  }

  template<typename... T>
  void set_intValue(T&&... t) {
    __clear();
    type_ = Type::intValue;
    new (&value_.intValue) int64_t(std::forward<T>(t)...);
  }

  template<typename... T>
  void set_stringValue(T&&... t) {
    __clear();
    type_ = Type::stringValue;
    new (&value_.stringValue) std::string(std::forward<T>(t)...);
  }

  template<typename... T>
  void set_intListValue(T&&... t) {
    __clear();
    type_ = Type::intListValue;
    new (&value_.intListValue) std::vector<int64_t> (std::forward<T>(t)...);
  }

  template<typename... T>
  void set_stringListValue(T&&... t) {
    __clear();
    type_ = Type::stringListValue;
    new (&value_.stringListValue) std::vector<std::string> (std::forward<T>(t)...);
  }

  const int64_t& get_intValue() const {
    assert(type_ == Type::intValue);
    return value_.intValue;
  }

  const std::string& get_stringValue() const {
    assert(type_ == Type::stringValue);
    return value_.stringValue;
  }

  const std::vector<int64_t> & get_intListValue() const {
    assert(type_ == Type::intListValue);
    return value_.intListValue;
  }

  const std::vector<std::string> & get_stringListValue() const {
    assert(type_ == Type::stringListValue);
    return value_.stringListValue;
  }

  int64_t& mutable_intValue() {
    assert(type_ == Type::intValue);
    return value_.intValue;
  }

  std::string& mutable_stringValue() {
    assert(type_ == Type::stringValue);
    return value_.stringValue;
  }

  std::vector<int64_t> & mutable_intListValue() {
    assert(type_ == Type::intListValue);
    return value_.intListValue;
  }

  std::vector<std::string> & mutable_stringListValue() {
    assert(type_ == Type::stringListValue);
    return value_.stringListValue;
  }

  int64_t move_intValue() {
    assert(type_ == Type::intValue);
    return std::move(value_.intValue);
  }

  std::string move_stringValue() {
    assert(type_ == Type::stringValue);
    return std::move(value_.stringValue);
  }

  std::vector<int64_t>  move_intListValue() {
    assert(type_ == Type::intListValue);
    return std::move(value_.intListValue);
  }

  std::vector<std::string>  move_stringListValue() {
    assert(type_ == Type::stringListValue);
    return std::move(value_.stringListValue);
  }

  Type getType() const { return type_; }

  uint32_t read(apache::thrift::protocol::TProtocol* iprot);
  uint32_t write(apache::thrift::protocol::TProtocol* oprot) const;
 private:
  Type type_;
  storage_type value_;

};



