C++0x 미리보기 3, 템플릿 별칭 (2부)

류광, 2007/12/08 22:03
보통의 형식에 대해서도 using을 이용해서 별칭을 정의할 수 있습니다. 그리고 그 이상의 것들에도 using을 사용할 수 있을지 모릅니다.

C++0x 미리보기 3, 템플릿 별칭 (1부)에서 이어지는 내용입니다.

1부에서 말했듯이 이 제안은 매개변수화된 형식(제안서에서는 ‘family of types’라고 칭합니다)에 대한 별칭을 using 키워드를 이용해서 정의하자는 것입니다. 더 나아가서 제안자들은 기존의 typedef가 하던 일, 즉 보통의 형식에 대한 별칭도 using으로 정의할 수 있게 하자고 제안합니다.

형식의 별칭은 아시다시피 typedef로 지정하는데, using을 사용한다면 이런 형태가 됩니다.

typedef unsinged int UINT;
using UINT = unsinged int; // 위와 동일한 의미

이렇게 단순한 예라면 typedef 구문과 using 구문의 차이는 전적으로 취향 문제일 수 있습니다만(그러나 꼭 그런 것은 아닙니다 - typedef라는 키워드 자체에 문제가 있는데, 잠시 후에 좀 더 이야기하겠습니다), 다음 예처럼 함수 포인터 형식의 별칭을 만들 때에는 눈에 띄는 차이가 생깁니다. 예를 들어 이런 typedef를 생각해 봅시다.

typedef int (*func_ptr_t)(double, const vector<string>&);

이것은 앞의 UINT 같은 기본적인 형식 별칭 선언에 쓰이는

typedef 기존이름 새이름;

이라는 틀에서 벗어나 있기 때문에, 함수 포인터 형식(C에서 물려 받은)에 익숙하지 않은 사람에게는 무엇이 새 이름이고 무엇이 원본인지가 눈에 잘 들어오지 않습니다. 반면 using을 사용하면 적어도 새 이름이 무엇인지는 확연하게 눈에 들어옵니다.

using func_ptr_t
  = int (*)(double, const vector<string>&);

그보다 더 큰 문제가 typedef 자체에 있습니다. typedef는 type definition의 약자이지만, 사실 typedef는 새로운 형식을 정의하는 것이 아닙니다. 단지 기존 형식의 또 다른 이름(별칭)을 정의할 뿐입니다. 만일 typedef가 정말로 새로운 형식을 정의하는 것이라면 다음 코드는 컴파일되지 않아야 합니다.

void f(unsigned int);

typedef unsigned int UINT;

void g(UINT u)
{
	f(u);
}

현재의 C++에서 이런 코드가 컴파일되는것은, UINT가 새로운(따라서 기존 형식들과 다른) 형식이 아니라 단지 기존 형식에 대한 또 다른 이름일 뿐이기 때문입니다.

제안자들이 바탕에 깔고 있는 생각은 아마도 typedef 자체를 차차 퇴출시키고, 모든 별칭을 using 키워드로 처리하자는 것이 아닌가 싶습니다. 표준 문구 수정안을 담은 현재 최신 제안서 N2258에는 매개변수화된 형식의 별칭과 함께 위와 같은 단순 형식의 별칭에 대한 제안만 포함되어 있습니다만, 전반적인 문제 의식과 여러 가지 아이디어들을 담고 있는 N1489에는 이름공간 별칭과 변수 및 함수 별칭에 대해서도 using을 사용할 수 있다는 점을 언급하고 있습니다. 아래의 사항들은 아직 표준위원회를 통과하지 않은 순수한 제안입니다만, 모든 별칭을 using으로 통합하자는 중요한 아이디어를 담고 있으므로 알아 둘 필요가 있을 것입니다.

이름공간 별칭의 경우 현재는 namespace 키워드를 사용하는데, N1489에는 아래의 예처럼 using 키워드를 이용한 구문이 나옵니다.

namespace Lib = MyLib::ThirdVersion;
using Lib = MyLib::ThirdVersion; // 위와 동일한 선언

다음으로 변수에 대한 별칭을 보자면... 현재 C++는 한정된 이름에 대한 using 선언문을 지원합니다.

using std::cout;

이것은 std 이름공간의 cout을 현재의 이름공간으로 도입하는 효과를 내는데, 달리 말하자면 std::cout에 cout이라는 새 이름을 붙이는 것과 마찬가지입니다. 이에 대해 N1489는 다음과 같은 형태의 구문을 제시합니다.

using cout = std::cout;

그리고 C++의 참조에 대해에서 이야기했듯이 참조는 별칭의 수단으로 쓰입니다. N1489에는 이런 예가 나오는데,

int i;
using r = i;

이는 int &r = i;와 같은 의미라고 해석할 수 있겠습니다. &에 비해 장점은 int를 반복하지 않아도 된다는 점입니다. int가 아니라 std::vector<std::list<int>*> 같은 긴 형식 이름이라면 장점이 더욱 두드러졌을 것입니다.[1]

더 나아가서 N1489는 함수에 대한 별칭도 언급하는데, 다음처럼 중복적재 버전들에 대한 별칭을 정의하는 예와,

#include <cmath>
using Cos = std::cos; // cos(float), cos(double) 등 cos의 모든 버전
using C = std::cos(double); // double std::cos(double)만.

함수 템플릿에 대한 예가 나옵니다.

template<class T>
using F = f<T, MyAllocator<T> >(int, char);

다시 말씀드리지만 현재 통과된 것은 템플릿 별칭과 typedef를 대신하는 형식 별칭 두 가지 뿐입니다. 위의 사항들이 모두 통과된다면 1부의 끝부분에서 말한 using 구문의 장점이 명백해 질 것입니다. 바로 일관성입니다.

그나저나 위의 사항들이 거부된 것인지 아니면 논의 중인지는 잘 모르겠는데, 새로운 내용을 담은 제안서가 나오면 다시 이야기하겠습니다.

[1] 그렇다고 using이 &를 완전히 대체할 수는 없을 것입니다. using은 식별 가능한 이름에만 사용할 수있지만 &는 이름이 없는 임시 객체를 참조하는 데에도 쓰이기 때문입니다.

top
트랙백 0 : 의견 # + 4

Trackback Address :: http://occamsrazr.net/tt/trackback/176

comments powered by Disqus

(2013년 11월 10일자로 블로그에도 DISQUS 시스템을 도입했습니다. 기존 의견의 수정, 삭제, 댓글 추가는 여전히 가능합니다.)

  1. nemonandes 2008/01/06 17:37 PERMALINKMODIFY/DELETE REPLY

    5번째 음영 박스 안에 "void g(UNIT u)" 함수 정의 부분에
    인자 형식 부분 오타가 있는 듯 합니다.

    새해 복 많이 받으시고요.. 2008년에도 번역, 블로깅 번창하세요..

  2. 류광 2008/01/06 19:47 PERMALINKMODIFY/DELETE REPLY

    수정했습니다. 고맙습니다~ 새해 복 많이 받으세요!

  3. 김윤수 2008/04/18 23:50 PERMALINKMODIFY/DELETE REPLY

    마지막 Comment에 지적하신 문제점은 using r = &i 와 같은 식으로 하면 되지 않을까요 ? reference에 대해서는 이런구문을 사용하면 지적하신 문제점이 없어질 것 같네요. using r = &(x+y) ^^

  4. 류광 2008/04/19 15:50 PERMALINKMODIFY/DELETE REPLY

    아 그런 구문도 가능하겠네요. 그런데 임시 객체에 대한 참조이니 소위 오른쪽값 참조가 되어서 using &&r = (x+y); 형태로 가는게 일관성이 있겠습니다.

    물론 이 이야기는 제안과는 무관합니다... :)

    참 그리고 "!!스팸방지 ... " 줄은 제일 마지막에 오게 해야 최근 댓글 목록에 그런 문구가 나타나지 않습니다. 그런데 이 방법 역시 뚫고 들어오는 스패머가 있군요. 다른 방법을 고민해봐야 하겠습니다....