본문 바로가기
번역/Bjarne Stroustrup's C++ Style and Technique FAQ

Why can't I define constraints for my template parameters?

by 겜게준 2020. 3. 4.

왜 템플릿 파라미터에 제약을 둘 수 없는건가요?

글쎄요, 꽤 쉽게 일반적으로 할 수 있습니다.

다음 예제를 생각해봅시다 :
template
void draw_all(Container& c)
{
for_each(c.begin(),c.end(),mem_fun(&Shape::draw));
}

위의 예제에 타입 에러가 있다고 하면, 상당히 복잡한 for_each() 호출에서 해결을 해야 할것입니다. 예를 들자면, 만약
container 요소의 타입이 int라고 하면, for_each() 호출과 관련된 발견하기 어려운 오류들이 발생할 것입니다.
(왜냐하면 int 타입에서 Shape::draw()를 호출할 수 없기 때문입니다.)
이런 오류를 미리 발견하기위해 다음과 같이 작성할 수 있습니다:
template
void draw_all(Container& c)
{
Shape* p = c.front(); // Shape*의 컨테이너만 허용됨

for_each(c.begin(),c.end(),mem_fun(&Shape::draw));
}

변수 "p"의 초기화에서 거의 모든 컴파일러에서 이해할 수 있는 오류 메시지를 출력할 것입니다.

위의 예제에서는 변수 "p"의 초기화에서 거의 모든 컴파일러에서 이해할 수 있는 오류 메시지를 출력할 것입니다. 이런 트릭은
모든 언어에서 흔한 것이고 모든 새로운 구성에서 개발되어야만합니다. 프로덕션 코드에서는 아마 다음과 같이 작성할 것입니다. :
template
void draw_all(Container& c)
{
typedef typename Container::value_type T;
Can_copy<T,Shape*>(); // accept containers of only Shape*s

for_each(c.begin(),c.end(),mem_fun(&Shape::draw));
}

이것을 이용해 assertion 처리를 한다는 것을 명확하게 전달할 수 있습니다. Can_copy 템플릿은 다음과 같이 정의될 수 있습니다. :
template struct Can_copy {
static void constraints(T1 a, T2 b) { T2 c = a; b = a; }
Can_copy() { void(*p)(T1,T2) = constraints; }
};

Can_copy는 (컴파일 시간에) T1이 T2에 대입할 수 있는지를 검사합니다.
Can_copy<T, Shape*>는 T가 Shape*타입인지, 또는 Shape에서 파생된 클래스의 포인터인지, 아니면 Shape*에 대한 사용자 정의 변환이 혀용된 타입인지를 검사합니다. 
Can_copy의 정의가 최소한 다음으로 좁혀지는것을 알아햐 합니다:
- 검사될 제약조건과 검사할 타입의 이름을 지정하는 줄
- 검사한 특정 제약 조건을 나열하는 줄 (constraints() 함수)
- 검사를 시작하는 방법을 제공하는 줄 (생성자)

추가적으로 Can_copy의 정의가 다음과 같은 요소들을 포함할 수 있습니다:
- 변수를 선언하거나 복사를 하지 않고 제약조건을 표현할 수 있으므로, 제약조건 작성자는 타입이 어떻게 초기화 되는지, 객체가 복사가 되거나 파괴가 될 수 있는지 여부 등을 가정할 필요가 없습니다.()
- 현재 컴파일러를 사용하여 제약 조건에 대한 코드가 생성되지 않음
- 제약조건을 정의하거나 사용하기 위한 매크로가 필요하지 않음
- 현재 컴파일러들은 "constraints" 단어와제약조건의 이름과 실패 원인에 대한 특정 에러를 포함한 실패한 제약조건에 대한 이해하기 쉬운 에러 메시지를 제공합니다. (예시 "double*를 이용하여 Shape*를 초기화 할 수 없습니다.")

그러면 언어에서는 Can_copy()와 같은 것이나 더 엘레강스한 것이 없는건가요? D&E(책 이름)에는 c++에 대한 일반 제약조건 표현에 관한 어려움에 대한 분석을 포함하고 있습니다. 그때부터 이러한 제약조건 클래스를 쉽게 작성하고 좋은 오류 메시지를 발생 할 수 있도록 하는 많은 아이디어가 등장했습니다. 예를 들자면 

댓글