#include <iostream>
#include <string>
#include <map>
using namespace std;
template <typename T>
using custom_map = map<string, T>;
#define custom_map2 map<string, int>
int main()
{
custom_map<int> dict;
dict["haha"] = 1;
cout << "haha: " << dict["haha"] << endl;
custom_map<string> dict2;
dict2["hello"] = "world";
cout << "hello: " << dict2["hello"] << endl;
custom_map2 dict3;
dict3["hehe"] = 2;
cout << "hehe: " << dict3["hehe"] << endl;
return 0;
}
/* 결과
haha: 1
hello: world
hehe: 2
*/
using | #define | |
---|---|---|
역할 | 타입(alias) 정의 | 전처리기 매크로 |
타입 안전성 | O (컴파일러가 타입으로 인식) | X (단순 문자열 치환) |
스코프(scope) | C++의 스코프 규칙을 따름 (ex: 네임스페이스 안에서도 사용 가능) | 전처리 단계에서 치환됨. 스코프 개념 없음. |
디버깅 및 오류 메시지 | 명확한 타입 이름 제공 | 에러 메시지에서 원래 타입 이름을 볼 수 없음 |
템플릿과 결합 | ✅ 가능 (using MyMap = std::map<key, value>;) | ❌ 불가능 |
추천 여부 | 강력 추천 | 웬만하면 지양 (특히 타입 정의에서) |
using
을 추천하는 이유1. 타입 시스템과 통합됨
using custom_map = map<string, int>;
는 실제로 새로운 타입 별칭이 생성된다. 이는 디버깅, 템플릿, 오버로딩 등에서 정확한 타입 추적을 가능하게 해준다.
2. 스코프와 네임스페이스 호환
using
은 네임스페이스 안에서 선언할 수 있어 구조화된 코드를 작성하기 좋다.
3. 템플릿에서 유연하게 사용 가능
template <typename T>
using vec = std::vector<T>;
4. 에러 메시지 명확
컴파일러가 타입 정보를 명확하게 인식하여, 디버깅 시 원인을 빠르게 파악할 수 있다.
#define
을 지양하는 이유#define custom_map2 map<string, int>
는 컴파일 전에 단순 문자열 대체이다.#define
을 상수 정의(값)에만 최소한으로 사용하고, 그마저도 constexpr
이나 const
로 대체하는 것이 좋다.using
을 사용하자.#define
은 정말 필요할 때만, 그리고 타입 정의에는 되도록 쓰지 말자.using
이 훨씬 강력하고 안전한 방식이다.typedef
와 using
은 모두 타입 별칭(type alias)을 만드는 데 사용되지만, 모던 C++에서는
using`이 더 강력하고 유연하다.
typedef int my_int;
using my_int = int;
my_int x = 5;
둘 다 my_int
를 int
로 정의한다.
typedef | using | |
---|---|---|
도입 시기 | 오랜된 문법(C 언어부터) | C++11에서 도입 |
템플릿과의 결합 | ❌ 어렵거나 불가능 | ✅ 매우 쉬움 |
가독성 | 때때로 예매함 | 명확함 |
표현력 | 제한적 | 표현력이 높고 확장 가능 |
코드 스타일 | 오래된 스타일 | 모던 C++ 스타일 |
✅ using
은 템플릿 타입 별칭 가능
template <typename T>
using vec = std::vector<T>;
템플릿에 기반한 새로운 타입을 만드는 데 매우 유용하다.
❌ typedef
는 템플릿 별칭 불가능
typedef std::vector<int> vec; // ok
// 하지만 템플릿으로는 지원 안됨.
using
을 사용하는 것이 권장된다.typedef
는 구형 스타일이며, 템플릿과 호환성이 낮아 유지보수에 불리하다.using
은 가독성, 유연성, 모던 C++ 스타일 모두에서 우수하다.