글 목록 보기

Atachment
첨부 '3'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

C++ 템플릿 상속엔 골 때리는 문제가 있는데 ...

바로 베이스클래스의 멤버에 접근하려면 베이스 클래스의 이름을 명시해야 한다는 것이다... 안그러면 이름을 못찾아온다

사람 상당히 귀찮게 만드는놈이라 할 수 있겠다.

보통 일반적으론 볼일이 없고 Mixin 을 이용하거나 아니면 Effective C++ 을 읽으면서 알게된다(책에는 "못찾는다" 라고 되어 있다)


간단히 말하면 이런 코드다

#include <cstdio>

void foo()
{
	printf("Global Function\n");
}
template <typename T>
class Cls1
{
	T Var1;
public:
	void foo()
	{
		printf("Member Function\n");
	}
};

template <typename T>
class Cls2 : public Cls1<T>
{
	T Var2;
public:
	void test()
	{
		Cls1<T>::foo();
	}
};

int main()
{
	Cls2<int> cls2;
	cls2.test();

	return 0;
}


근데 만약 명시 하지 않으면 어떻게 될까?


일단 최신의 VC++ 2012에서 돌려보자

01.png


헐...? 정확히 멤버 함수를 찾아온다. 여기엔 올리지 않겠지만 VS2005~2010 도 모두 같은 동작을 한다.

다른컴파일러에서 해보자. gcc 4.4다.


02.png


헐?! 글로벌 함수를 찾는다 (...) 이거뭥미.


그럼 최신의 C++0x를 지원하는 gcc4.7에서 해보자.


03.png


역시 전역함수를 찾는다.


표준문서는 귀찮아서 (...) 확인하지 않았지만 관련 서적 등을 보면 gcc의 동작이 맞는 것으로 보인다.
하지만 저런 코드를 짜면서 gcc 쪽 동작을 원하는 사람이 과연 있을까... 하는 생각이 든다. 일반적인 클래스를 만드는 느낌으로 당연히 멤버함수가 호출 될 것이라고 생각 하지 않을까? 이 결과를 확인하면서 C++은 당최 생각대로 움직여 주지 않는 매저키스트 들을 위한 언어란 누군가의 말이 귓가에 맴돈다 (...)


결론 : EC++에 나온대로 그냥 제대로 포커스 지정 하자 (...) 야!


PS. gcc 에서는 저렇게 두가지 모두 있는 경우가 아니라 전역 foo 함수가 없는 (즉 이름을 찾을 수 없는) 경우에는 당연히 이름을 찾지 못해 에러를 내는데, 이 경우 컴파일 옵션에 -fpermissive 를 추가 하는 것으로 멤버함수로의 연결이 가능하다(워닝은 뜬다)
단 전역 foo 함수가 존재 할 경우 저 옵션을 그냥 무시하고 그냥 전역 함수로 연결해 버린다.


PS2. 혹시 LLVM-clang 을 사용할 수 있는 환경에 계신분은 어떤 결과가 나오는지 알려주시면 좋겠다.



?
  • ?
    123 2012.09.03 03:48
    VS 에서는 자동으로 찾아주네요.. 역시 상용이라 틀린가보네요..
    clang 으로 컴파일 해서 실행해보니 gcc 하고 같네요. .
    관련글에는 이렇게 나오네요
    While non-dependent names are resolved "normally" – when the template is defined,
    the resolution for dependent names happens at the point of the template’s instantiation.
    그러까 템플릿 인스턴스시 resolve 가 되게할려면 dependent name 으로 만들어 줘야 되네요
    Cls1<T>::foo() or this->foo() 이런식으로..

    http://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates/