using namespace std; ...C++11에서 using의 기능을 새롭게 추가하였는데 그것이 타입 별칭(Type alias)을 선언하는 것이다. 기존에 typedef라는 키워드를 이용해서 STL 등에서 제공하는 긴 iterator 타입을 간단하게 선언해서 사용해 본 경험이 많이들 있을 거라고 생각한다. using을 이용한 타입 별칭 선언은 typedef가 하는 일과 마찬가지로 기존 타입을 새로운 이름으로 선언하는 것이다. 아래 함수 포인터 타입을 선언하는 2가지 예를 보면서 어떤 게 더 보기 좋은지 한번 생각해보자.
typedef void (*FP)(int, const std::string&); // typedef 이용 using FP = void (*)(int, const std::string&); // using 이용다른 건 몰라도 함수 포인터 타입을 선언할 때는 using이 훨씬 분명하게 뜻이 전달되는 것 같다. 하지만 이것만이 기존 typedef를 사용하던 습관을 버리고 using을 사용해야 할 이유라면 아마도 typedef가 익숙한 개발자에게는 별로 납득할만한 이유는 되지 못할 것 같다. Effective Modern C++책 에서는 typedef보다는 using을 사용하라고 권장하며 그 이유에 대해서도 설명하고 있는데 여기서 그 이유에 대해 정리를 해 보려고 한다.
using을 이용한 타입 선언이 typedef와 크게 구별되는 점이 하나 있다. using의 경우에는 템플릿화가 되지만 typedef는 그렇지 못하다는 점이다. 아래 예를 보자.
template<typename T> // std::list<T, MyAlloc<T>>의 별칭은 MyAllocList<T> using MyAllocList = std::list<T, MyAlloc<T>>; MyAllocList<Widget> lw; // client codeC++11에서는 이렇게 using을 이용해서 간단히 T에 따라 변화하는 템플릿 타입의 별칭을 선언할 수 있지만 기존 typedef의 경우에는 템플릿화할 수 없기 때문에 이러한 목적을 이루기 위해서 아래 예와 같은 방법을 사용하였다.
template<typename T> // std::list<T, MyAlloc<T>>의 별칭은 MyAllocList<T>::type struct MyAllocList { typedef std::list<T, MyAlloc<T>> type; }; MyAllocList<Widget>::type lw; // client code템플릿 구조체를 하나 선언해서 그 안에서 typedef를 이용하여 별칭을 선언하는 것이다. 이렇게 함으로써 실제 타입을 사용할 때 "::type"을 덧붙인다는 소소한 불편함을 제외하면 같은 동작을 하도록 할 수 있었다. 하지만 이렇게 선언된 타입은 템플릿 안에서 사용할 때 또 다른 불편함이 발생한다. 아래 예를 보자.
template<typename T> class Widget { private: typename MyAllocList<T>::type list; // MyAllocList<T>를 멤버로 선언 ... };MyAllocList
template<typename T> using MyAllocList = std::list<T, MyAlloc<T>>; template<typename T> class Widget { private: MyAllocList<T> list;// "typename", "::type"이 없다. ... };
참고로 한 가지 더 정리하자면 using을 이용한 타입의 별칭 선언은 C++11에서 추가되었지만 STL의 많은 코드는 이전과의 호환성 때문에 이전 방식인 구조체 안에 type을 선언하는 방식을 그대로 유지하고 있다. 하지만 C++14에서는 이전보다 더 간단하게 사용할 수 있도록 같은 기능을 제공하는 템플릿 선언들을 추가로 제공한다. 아래 예에서 보듯이 기존 구조체 이름에 '_t'를 붙여서 같은 기능을 제공하도록 선언하였다.
std::remove_const<T>::type // C++11: const T → T std::remove_const_t<T> // C++14 버전 std::remove_reference<T>::type // C++11: T&/T&& → T std::remove_reference_t<T> // C++14 버전 std::add_lvalue_reference<T>::type // C++11: T → T& std::add_lvalue_reference_t<T> // C++14 버전위 예는
0 개의 댓글:
댓글 쓰기