5

可能重复:
在 C++ 中扩展枚举?

我正在使用一个库,它将自己的一组错误定义为枚举类型。

枚举错误类型 {...}

该库还具有一个采用该枚举类型并打印错误的函数。

无效设置状态(错误类型新错误)

如果我想定义自己的错误,并将其提供给 set_status 函数,是否可以以某种方式扩展 error_type 枚举,或者覆盖它?

4

1 回答 1

16

可能有一些锋利的边缘,但我认为这应该适合你:

#include<iostream>

// Helper struct

template<typename T, int N, typename... LIST>
struct whereInType {
  static const int index = -1;
};

template<typename T, int N, typename HEAD, typename... TAIL>
struct whereInType<T,N,HEAD,TAIL...> {
  static const int index = whereInType<T, N+1, TAIL...>::index;
};

template<typename T, int N, typename... TAIL>
struct whereInType<T,N,T,TAIL...> {
  static const int index = N;
};

// The actual union type

template<typename... ENUMS>
class enum_union {
public:
  template<typename ENUM>
  constexpr enum_union(ENUM val) :
    which_enum(whereInType<ENUM,0,ENUMS...>::index),
    value(val) {}
  constexpr operator long long(){
    return static_cast<long long>(which_enum)<<32 | value;
  }
  template<typename ENUM, int IGNORE=0>
  constexpr bool operator==(const ENUM& e) {
    return *this == enum_union<ENUMS...>(e);
  }
  template<int IGNORE=0>
  constexpr bool operator==(const enum_union<ENUMS...>& oth) {
    return which_enum==oth.which_enum && value==oth.value;
  }
  template<typename T>
  constexpr bool operator!=(const T& oth) {
    return !(*this == oth);
  }
private:
  int which_enum;
  int value;
};

// An example usage

enum normal_errors {
  E_OUTOFMEMORY,
  E_IOERROR
};

enum weird_errors {
  E_OUTOFAARDVARKS,
  E_DIVIDEBYCUCUMBER
};

typedef enum_union<normal_errors, weird_errors> any_error;

// Some tests

void print(any_error e) {
  switch(e) {
  case any_error(E_OUTOFMEMORY):
    std::cout << "Out of Memory\n";
    break;
  case any_error(E_IOERROR):
    std::cout << "I/O Error\n";
    break;
  case any_error(E_OUTOFAARDVARKS):
    std::cout << "WE NEED AARDVARKS!!!  NOW!!!!!\n";
    break;
  case any_error(E_DIVIDEBYCUCUMBER):
    std::cout << "please reinstall universe\n";
    break;
  }
}  

main(){
  print(E_OUTOFMEMORY);
  print(E_IOERROR);
  print(E_OUTOFAARDVARKS);
  print(E_DIVIDEBYCUCUMBER);
  if (any_error(E_OUTOFMEMORY) == E_OUTOFAARDVARKS) {
    std::cout<<"bad\n";
  }else{
    std::cout<<"good\n";
  }
  if (any_error(E_OUTOFMEMORY) != E_OUTOFAARDVARKS) {
    std::cout<<"good\n";
  }else{
    std::cout<<"bad\n";
  }
  if (any_error(E_OUTOFMEMORY) == E_OUTOFMEMORY) {
    std::cout<<"good\n";
  }else{
    std::cout<<"bad\n";
  }
  if (any_error(E_OUTOFMEMORY) != E_OUTOFMEMORY) {
    std::cout<<"bad\n";
  }else{
    std::cout<<"good\n";
  }
}
于 2013-01-24T18:41:25.483 回答