2014-12-21 6 views
2

나는 내 자신의지도를 구현하고 있는데 이것은 코드 조각입니다.템플릿 클래스가 중첩 된 템플릿 클래스, g ++가 잘 컴파일 됨, vs2013이 컴파일되지 않음

template<typename KEY, typename VAL> 
Map<KEY,VAL>::MapPair<KEY,VAL> Map<KEY,VAL>::make_map_pair(KEY k, VAL v){ 
    return MapPair<KEY,VAL>(k,v); 
} 

template<typename KEY, typename VAL> 
template<typename K, typename V> 
Map<KEY,VAL>::MapPair<K,V>& Map<KEY,VAL>::MapPair<K,V>::setKey(K keyp, V val){ 
    key = keyp; 
    value = val; 
} 

클래스 데프는 다음과 같다 : 나를 괴롭히는되는 코드의 일부는이 두 선언이다

template <typename KEY, typename VAL> 
class Map{ 
private: 
    template<typename K, typename V> 
    class MapPair { 
    public: 
     K key; 
     V value; 
     MapPair(){}; 
     MapPair(K key, V value); 
     MapPair<K,V>& setKey(K key, V val); 
     V& getValue(); 
     K getKey(); 
     bool operator==(MapPair<K,V> item); 
    }; 

    List<MapPair<KEY,VAL>> pair_list_; 
    MapPair<KEY,VAL> make_empty_map_pair(KEY k); 
    MapPair<KEY,VAL> make_map_pair(KEY k, VAL v); 
public: 
    Map(){} 
    bool exists(KEY key); 
    VAL& operator[](KEY key); 
    VAL pop_pair(KEY key); 
}; 

이 코드는 ++ g에서 들여다없이 컴파일하지만 비주얼 스튜디오 2013가 밖으로 플립 오류 :

error C2059: syntax error : ')' 
error C2059: syntax error : ')' 

각 상위 함수 정의는 오류를 생성합니다. debain 7.5

g++ -Wall -c -std=c++11 vm.cpp 
g++ vm.o -o vm 

에서

++ g에서

과는 전혀 실행시 문제를 잘 실행하고 어떻게해야 무엇을한다.

질문은 왜 g ++에서이 문제를 해결하고 vs2013을 컴파일하지 않습니까? vs2013에서이 코드를 올바르게 컴파일하려면 어떻게해야합니까? 필자가 작성한 코드에서 이식성을 보장하기 위해 어떤 종류의 습관을 개발할 수 있습니까?

+0

:: 템플릿 : 여기에 같은 문제에 대한 논의가 있었다

template<typename KEY, typename VAL> typename Map<KEY,VAL>::template MapPair<KEY,VAL> Map<KEY,VAL>::make_map_pair(KEY k, VAL v) { return MapPair<KEY,VAL>(k,v); } 

MapPair ' –

+0

이 코드를 컴파일하는 데 g ++의 정확한 버전은 사용 되었습니까? –

+0

이것은 http://stackoverflow.com/questions/18344580/can-typename-be-omitted-in-the-type-specifier-of-an-out-of-line-member-definitio와 같은 질문입니다. 결론적으로 대답하지 못했습니다 – willj

답변

4

따라서 VS2013은 중첩 클래스의 반환 유형 앞에 typename이 삽입 된 것을 좋아합니다. 내가 할 수 있다는 것을 알았지 만,이 경우까지 왜 나는 ID를 모른다.

template<typename KEY, typename VAL> 
typename Map<KEY,VAL>::MapPair<KEY,VAL> Map<KEY,VAL>::make_map_pair(KEY k, VAL v){ 
/*^^^^^ right here before the nested class object that it will return.*/ 
    return MapPair<KEY,VAL>(k,v); 
} 

g ++이 필요하지 않더라도 코드가 덜 변경되어 포팅 될 수 있도록하는 것이 가장 좋습니다.

+0

'template' 누락되었습니다.'typename Map :: template MapPair ' – willj

2

C++ 11 표준을 읽으면 typename이 필요합니다. VS2013이 옳은 일을하고 있습니다.

typename 키워드가 없으면 종속 이름이 유형을 지정하지 않는다고 가정합니다.

14.6 이름 확인 템플릿 선언 또는 정의에 사용 된 [temp.res]

2) 이름과 그 이 해당하지 않는 유형 이름하지 상정 된 틀 파라미터에 의존 이름 조회가 유형 이름을 찾거나 이름이 의 자격을 갖춘 경우 typename 키워드를 사용합니다. 자격-ID가 현재 인스턴스 과 중첩 이름 지정자의 구성원이 아닌 형태를 의미한다

3) 종속 형 지칭이를 키워드 유형 이름 접두사한다 이전의 이름을 언급 할 때 선언자-ID이, 키워드 유형 이름이 필요하지 않습니다 다음과 같은 클래스 템플릿의 멤버의 정의 내에서 클래스 템플릿 또는 의 정의 내에서

7)

는 선언 유형을 선언하는 클래스 템플릿의 멤버입니다.[참고 : 오브젝트 식의 형태는 현재 인스턴스화

14.6.2.1 의존 때 이러한 이름은 규정되지 않은 이름을 룩업 현재 인스턴스 또는 반원 액세스 식 조회로 반원 조회를 사용하여 발견 될 수있다 이

    기본 클래스 템플릿의 정의
  • 또는 차의 구성원 인 경우 타입 [temp.dep.type]는

    위한 이름은 현재 인스턴스 지칭 (아래 설명) Map<KEY, VAL>Map의 정의에서 사용되는 경우 가 <>

묶인 클래스 템플릿, 기본 템플릿의 템플릿 인수 목록 뒤에 클래스 템플릿의 이름, 그 의미 현재 인스턴스화make_map_pair의 구문 분석시 Map<KEY, VAL>::으로 규정 된 형식 이름은 현재 클래스 구성원 이름 조회에서 현재 인스턴스화으로 찾을 수 있습니다.

그러나 C++ 파서가 선언자 -id 앞에 구성원 함수 정의의 반환 유형 인 Map<KEY, VAL>을 발견하면 아직 둘러싸는 클래스의 이름을 발견하지 못했습니다. 파서는이 시점에서 Map이 둘러싼 클래스를 참조하는지 여부를 판단 할 수 없습니다.

Map<KEY, VAL>이 현재 인스턴스 이름을 지정하는지 여부에 관계없이 - 표준에서는 선언자 -id 앞에있는 클래스 템플릿의 멤버 정의 내에서 typename을 생략 할 수 없습니다.

본이 카토의이 example는 연타/GCC의 행동에 일관성이 있음을 입증하고, 유사한 시나리오에서 typename이 필요합니다

template <typename T> 
struct A { 
    typedef int X; 
    X f(); 
}; 

template <typename T> 
A<T>::X A<T>::f() // error: missing 'typename' 
{ 
} 
우리가 이름 Map가 좌우된다는 결론을 내릴 경우

typename 그런 다음 필요 template 키워드도 필요합니다 :

14.2 이름 템플릿의 특수화 [temp.names]

정규화 된 ID의 중첩 된 이름 지정자와 중첩 된 이름의 뒤에 . 또는 -> 뒤에 구성원 템플릿 전문의 이름이 나타나고 postfix-expression의 개체 또는 포인터식이 또는 중첩 된 경우 qualified-id의 -name-specifier는 템플릿 매개 변수 (14.6.2)에 의존하지만 현재 인스턴스화 (14.6.2.1)의 멤버를 나타내지는 않으며 멤버 템플릿 이름 앞에 키워드 이라는 접두사가 있어야합니다. 그렇지 않으면 이름은 비 템플릿입니다.

수정 된 예는 다음과 같습니다 Can typename be omitted in the type-specifier of an out of line member definition?하여 함수의 반환 형식이 유형 이름의지도 '로 선언 sohuld