typedef 지정자
typedef 지정자
typedef는 (아마 복잡할) 타입 이름 대신 아무 데서나 쓸 수 있는 별명을 만들어 주는 지정자예요. "이 타입이 너무 길어서 매번 적기 힘들다" 싶을 때, 그리고 코드 어디에서든 그 타입을 가리키는 짧은 이름이 필요할 때 쓰죠. 여기서는 typedef가 정확히 어떤 선언을 만드는지, 그리고 어디에 쓰면 안 되는지까지 규칙 기준으로 정리해 볼게요.
출처: cppreference
본문
설명
typedef 지정자는 선언 안에서 쓰일 때, 그 선언을 변수나 함수 선언이 아니라 typedef 선언으로 만드는 역할을 해요.
typedef는 보통 선언의 맨 앞에 쓰지만, 타입 지정자 뒤나 두 타입 지정자 사이에 붙어도 허용돼요. 다만 타입 지정자 외에 다른 지정자는 함께 쓸 수 없어요.
typedef 선언은 한 줄에 여러 식별자를 선언할 수 있어요(예: int와 int에 대한 포인터). 배열·함수 타입, 포인터·참조, 클래스 타입 등도 선언할 수 있죠. 이 선언에서 도입된 모든 식별자는 typedef 이름이 되는데, 그 이름은 typedef 키워드를 뗐을 때 그 자리에 오게 될 객체나 함수의 타입과 같은 뜻의 별명이에요.
typedef 이름은 기존 타입의 별명이지, 새 타입을 선언하는 게 아니에요. typedef로 기존 타입 이름(typedef 이름 포함)의 의미를 바꿀 수는 없어요. 한 번 선언된 typedef 이름은 같은 타입을 다시 가리킬 때만 다시 선언될 수 있어요. typedef 이름은 보이는 스코프 안에서만 효력을 가지므로, 서로 다른 함수나 클래스에 같은 이름의 타입이 다른 뜻으로 정의될 수 있어요.
typedef 지정자는 함수 매개변수 선언이나 함수 정의의 decl-specifier-seq에는 들어갈 수 없어요.
void f1(typedef int param); // ill-formed
typedef int f2() {} // ill-formed
또한 선언자가 없는 선언에도 typedef를 쓸 수 없어요.
typedef struct X {}; // ill-formed
링키지를 위한 typedef 이름 (typedef name for linkage purposes)
typedef 선언이 익명 클래스나 익명 열거형을 정의한다면, 그 선언이 만든 클래스 타입·열거형 타입의 첫 번째 typedef 이름이 바로 그 타입의 "링키지를 위한 typedef 이름"이 돼요.
예를 들어 typedef struct { /* ... */ } S;에서 S가 링키지를 위한 typedef 이름이에요. 이렇게 정의된 클래스·열거형 타입은 외부 링키지(external linkage)를 가져요(익명 네임스페이스에 있지 않다면).
| 이렇게 정의된 익명 클래스는 C 호환 구성 요소만 담아야 해요. 특히 다음이 금지돼요. |
|---|
| 비정적 데이터 멤버, 멤버 열거형, 멤버 클래스 외의 멤버를 선언하기 |
| 기반 클래스나 기본 멤버 초기화기(default member initializer)를 갖기 |
| 람다 표현식을 포함하기 |
| 그리고 모든 멤버 클래스도 이 요구 사항을 (재귀적으로) 만족해야 해요 |
참고
| 타입 별명(type alias)은 typedef 선언과 같은 기능을 다른 문법으로 제공하며, 템플릿 이름에도 적용할 수 있어요. | (since C++11) |
키워드
typedef
예제
// simple typedef
typedef unsigned long ulong;
// the following two objects have the same type
unsigned long l1;
ulong l2;
// more complicated typedef
typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10];
// the following two objects have the same type
int a1[10];
arr_t a2;
// beware: the following two objects do not have the same type
const intp_t p1 = 0; // int *const p1 = 0
const int *p2;
// common C idiom to avoid having to write "struct S"
typedef struct { int a; int b; } S, *pS;
// the following two objects have the same type
pS ps1;
S* ps2;
// error: storage-class-specifier cannot appear in a typedef declaration
// typedef static unsigned int uint;
// typedef can be used anywhere in the decl-specifier-seq
long unsigned typedef int long ullong;
// more conventionally spelled "typedef unsigned long long int ullong;"
// std::add_const, like many other metafunctions, use member typedefs
template<class T>
struct add_const
{
typedef const T type;
};
typedef struct Node
{
struct listNode* next; // declares a new (incomplete) struct type named listNode
} listNode; // error: conflicts with the previously declared struct name
// C++20 error: "struct with typedef name for linkage" has member functions
typedef struct { void f() {} } C_Incompatible;
더 알아보기
- 타입 별명(type alias)은
typedef와 같은 기능을 더 간결한 문법으로 제공하는데, 타입 별명 문법 문서에서 확인할 수 있어요. - cppreference의 typedef 원문에서 결함 보고(defect report) 기록을 더 볼 수 있어요.