(어떻게) 열거 형의 항목을 계산할 수 있습니까?


98

이 질문이 떠 올랐습니다.

enum Folders {FA, FB, FC};

각 폴더에 대한 컨테이너 배열을 만들고 싶었습니다.

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(사용은 사용하기에 훨씬 더 우아 매핑 : std::map<Folders, ContainerClass*> m_containers;)

그러나 원래 질문으로 돌아가려면 배열 크기를 하드 코딩하지 않으려면 폴더에 몇 개의 항목이 있는지 알아내는 방법이 있습니까? (예를 들어 내가 잘못하지 않은 경우 FC와 같은 것을 허용하는 목록의 마지막 항목에 의존하지 않고 ContainerClass*m_containers[FC+1].)


이 게시물은 귀하의 질문에 답할 수 있습니다 : stackoverflow.com/questions/1390703/enumerate-over-an-enum-in-c .
StackedCrooked 2010 년

1
질문은 약간 불명확합니다. C ++ 표준 int(FA) | int(FB) | int (FC)에 따라 Folders변수 의 유효한 값이기도 합니다. 변수가 유효한 인덱스가 m_containers되도록 크기를 조정 하는 경우 충분히 크지 않습니다. Folders[FC+1]
MSalters 2011

나는에 매우 관련 일 요청했습니다 stackoverflow.com/questions/12972317/count-on-enum-c-automatic
sergiol

답변:


123

이 작업을 수행하는 좋은 방법은 없습니다. 일반적으로 열거 형에 추가 항목이 표시됩니다.

enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};

따라서 다음을 수행 할 수 있습니다.

int fuz[FOOBAR_NR_ITEMS];

그래도 여전히 좋지는 않습니다.

그러나 물론 열거 형의 항목 수만 안전하지 않다는 것을 알고 있습니다.

enum foobar {foo, bar = 5, baz, quz = 20};

항목의 수는 4 개이지만 열거 형 값의 정수 값은 배열 인덱스 범위를 벗어납니다. 배열 인덱싱에 열거 형 값을 사용하는 것은 안전하지 않으므로 다른 옵션을 고려해야합니다.

편집 : 요청에 따라 특별 항목을 더 돋보이게했습니다.


27
LAST 또는 ALWAYS_AT_END 또는 그렇게 비밀스럽지 않은 것으로 부르십시오. 그것을 확인 내밀어 . 따라서 후속 관리자가 마커를 종료 한 후 실수로 새 항목을 추가하지 않도록합니다.
Martin York

3
좋든 나쁘 든 이것이 우리 조직에서 취하는 접근 방식입니다. 일반적으로 FINAL_foobar_ENTRY와 같이 FINAL_enumname_ENTRY라고합니다. 또한 사람들이 enum 선언 바로 뒤에 정의 된 별도의 정적 const FOOBAR_COUNT 변수를 사용하는 것을 보았습니다. 이는 약간 오류가 발생하기 쉬운 접근 방식입니다.
Darryl

1
적어도 "enum foo {a = 10, LAST}"가 이상 할 것임을 아는 것은 상당히 쉽습니다. 그리고 "INT의 편곡이 [LAST]를"이 경우,하지 2, 그래서 대부분의 코드가 작동 11 개 항목 것이라고 생각 (하지만 잘못된 인덱스 값에있어 낭비 메모리)
코드 Abominator

32

C ++의 경우 다양한 형식 안전 열거 기술을 사용할 수 있으며 그중 일부 (예 : 제안되었지만 제출되지 않은 Boost.Enum )에는 열거 형 크기를 가져 오기위한 지원이 포함됩니다.

C 및 C ++에서 작동하는 가장 간단한 방법은 각 열거 형 유형에 대해 ... MAX 값을 선언하는 규칙을 채택하는 것입니다.

enum Folders { FA, FB, FC, Folders_MAX = FC };
ContainerClass *m_containers[Folders_MAX + 1];
....
m_containers[FA] = ...; // etc.

편집 : { FA, FB, FC, Folders_MAX = FC}대 관련 {FA, FB, FC, Folders_MAX]: 몇 가지 이유로 ... MAX 값을 열거 형의 마지막 법적 값으로 설정하는 것을 선호합니다.

  1. 상수의 이름은 기술적으로 더 정확합니다 ( Folders_MAX가능한 최대 열거 형 값을 제공하기 때문에 ).
  2. 개인적으로 나는 Folders_MAX = FC다른 항목들보다 더 눈에 띄는 느낌이 든다 (마틴 요크가 언급 한 문제인 최대 값을 업데이트하지 않고 실수로 열거 형 값을 추가하는 것이 조금 더 어려워 짐).
  3. GCC에는 다음과 같은 코드에 대해 "스위치에 포함되지 않은 열거 값"과 같은 유용한 경고가 포함되어 있습니다. Folders_MAX == FC + 1을 사용하면 스위치에 포함되어서는 안되는 일련의 ... MAX 열거 값이 생성되므로 이러한 경고가 깨집니다.
스위치 (폴더) 
{
  사례 FA : ...;
  케이스 FB : ...;
  // 죄송합니다. FC를 잊어 버렸습니다!
}

3
하지 않는 이유 : enum Folders { FA, FB, FC, Folders_MAX }; ContainerClass *m_containers[Folders_MAX];?
Bill

1
나는 마지막이 숫자라는 것을 분명히하고 싶습니다. 그리고 그들은 모두 같은 이름을 가지고 있습니다 :struct SomeEnum { enum type {FA, FB, FC, NB__};};
Luc Hermitte

2
사실 나는 그 "유용한"경고가 엉덩이에 옳은 고통이라고 느낀다. 나는 개발할 때 항상 -Wall -pedantic 등을 설정하는 좋은 경고를 좋아하지만 이러한 경고는 단지 어리 석다. &&에 대한 괄호를 제안하는 것과 같은 몇 가지 더 나쁜 것이 있습니다 || 및 & ^ | 연산자 우선 순위. 내 말은, 자바가 베이비 시터 언어라고 생각했는데, C와 C ++에서 도대체 무슨 일이 일어나고 있는지 ...
wich

2
Folders_max = FC의 단점은 열거 형에 무언가를 추가 할 때마다 변경해야한다는 것입니다!
에티엔

2
enum 폴더 {FA, FB, FC, Folders_MIN = FA, Folders_MAX = FC}; 반복에 유용하다는 것을 강조하기 위해?
gjpc 2015-06-11

7

STL 방식의 특성은 어떻습니까? 예를 들면 :

enum Foo
{
    Bar,
    Baz
};

쓰다

std::numeric_limits<enum Foo>::max()

전문화 (c ++ 11을 사용하는 경우 constexpr). 그런 다음 테스트 코드에서 std :: numeric_limits :: max () = last_item이라는 제약 조건을 유지하기 위해 정적 어설 션을 제공합니다.


2
불행히도 이것은 이 답변에 따라 작동하지 않습니다 .
rr-

3
std::numeric_limits<enum Foo>::max()항상 0을 반환합니다 ... (링크 된 답변에 대한 질문 참조) 일반 열거 형 ( enum Foo { ... }), 유형 힌트 열거 형 ( enum class Foo : uint8_t { ... })에서 gcc 5.2.0 @ Linux 및 MinGW 4.9.3 @ Windows에서 테스트되었습니다 .
rr-

1
(... 그리고의 경우 std::numeric_limits<std::underlying_type<Foo>::type>::max()기본 유형의 최대 값, 즉 32 비트 정수에 대해 0xFFFFFFFF를 반환합니다.이 컨텍스트에서는 유용하지 않습니다.)
rr-

1
내가 설명한 것을 수행하는 작업 코드가 있기 때문에 이상합니다. namespace gx { enum struct DnaNucleobase : char { A, C, G, T }; } 그런 : namespace std { template<> struct numeric_limits<enum ::gx::DnaNucleobase> { typedef enum ::gx::DnaNucleobase value_type; static constexpr value_type max() { return value_type::T; } (...) 그리고 std::cout << std::numeric_limits<::gx::DnaNucleobase>::max() << std::endl;인쇄 결과를 예상했다. gcc 5.2.1 및 4.8 / 4.9 맛으로 테스트되었습니다.
Wojciech Migda 2015

2
-1; 대답을 변경하면 저에게 핑을 보내면 반대 투표를 취소 할 수 있습니다. 이 대답은 따라야 할 나쁜 관습입니다. 의 개념을 오용 한 것입니다 numeric_limits<T>::max(). 함수가 합리적으로 반환 할 수있는 유일한 것은 가장 높은 열거 값입니다. 을 반환 2하지만 OP (이 특정 경우)는를 반환하는 데 필요합니다 3. 열거 형 ( FB = 2057)에 대해 기본값이 아닌 값이 있으면 모든 베팅이 해제 + 1되고 개별 오류를 해킹 할 수도 없습니다 . 이 있다면 numeric_limits<T>::number_of_elements_of_the_set()(또는 짧은 이름), 그 모호함없이 사용할 수 있습니다.
Merlyn Morgan-Graham

3

열거 형 끝에 Folders_MAX 또는 이와 유사한 항목을 추가하고 어레이를 초기화 할 때이 값을 사용합니다.

ContainerClass* m_containers[Folders_MAX];

2

열거 형을 함수에 대한 인수로 사용하고 싶습니다. 고정 된 "옵션"목록을 제공하는 쉬운 방법입니다. 여기서 가장 많이 득표 한 답변의 문제점은이를 사용하여 클라이언트가 "잘못된 옵션"을 지정할 수 있다는 것입니다. 스핀 오프로 본질적으로 동일한 작업을 수행하는 것이 좋지만 열거 형 외부의 상수 int를 사용하여 개수를 정의합니다.

enum foobar { foo, bar, baz, quz };
const int FOOBAR_NR_ITEMS=4;

유쾌하지는 않지만 상수를 업데이트하지 않고 열거 형을 변경하지 않으면 깨끗한 솔루션입니다.


1

C ++에서 열거 형 값의 수를 실제로 얻을 수있는 방법이 없습니다. 너무 크거나 너무 작은 배열을 만드는 상황에서 실행할 수있는 값을 정의하는 경우 열거 형 값을 정의하지 않는 한 앞서 언급 한 솔루션은 모두 작동합니다.

enum example{ test1 = -2, test2 = -1, test3 = 0, test4 = 1, test5 = 2 }

이 예제에서 결과는 5 개 항목의 배열이 필요할 때 3 개 항목의 배열을 생성합니다.

enum example2{ test1 , test2 , test3 , test4 , test5 = 301 }

이 예제에서 결과는 5 개 항목의 배열이 필요할 때 301 개 항목의 배열을 생성합니다.

일반적인 경우이 문제를 해결하는 가장 좋은 방법은 열거 형을 반복하는 것이지만 아직 내가 아는 한 표준에는 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.