0

템플릿 전문화 및 네임 스페이스 자격과 관련하여 C++의 규칙은 무엇입니까? 다음 코드와 동등한 코드를 가지고 있었고 템플릿 전문화 초기화에 관한 C++의 규칙을 이해하지 못한다는 것을 깨달았습니다. 처음에는 g::F<>의 전문화가 심지어 h 안에 허용된다는 것이 나에게 이상하게 보입니다. 그러나 주어진 사실을 나는 왜 그런 식으로 행동하는지 모르겠다.템플릿 전문화/초기화 및 네임 스페이스?

namespace g { 

    struct N { 
    N(char c):c_(c){} 
    char c_; 
    }; 

    template <typename V> 
    struct F { 
    static N n_s; // <-- want to initialize these for specializations 
    }; 

    namespace h { 
    struct X { static constexpr char k{'x'}; }; 

    template <> N F<char>::n_s{h::X::k}; // OK 
    template <> N F<int>::n_s{X::k};  // fails on "‘X’ not declared" 
    } 
} // namespace g 

// Seems weirdest to me. N and F need full qualifications but X doesn't. 
template <> g::N g::F<float>::n_s{h::X::k}; // OK also! 

템플릿 정적 멤버 이니셜 라이저는 g 공간을 유추 마지막 인스턴스화/초기화, 그것은 템플릿 행위 것처럼 보일 수 있습니다 그것은이 같은 코드에 같은 장소에있는 것처럼 이니셜 역할 마치 템플릿 정의 자체.

이 동작을 규정하는 사양의 규칙은 무엇입니까? 에서

답변

-1

(...이 GCC 4.8.1 테스트 및 버그 등 지금까지 조금 보이는 것을 주) :

F<int>::n_s과 관련된 네임 스페이스가 g이기 때문에 실패
template <> N F<int>::n_s{X::k};  // fails on "‘X’ not declared" 

반면, Xg::h에 선언되어 있습니다. 그래서 h::F<int>::n_s처럼 철자를 써야합니다.

+0

huh? g :: F :: n_s와 같은 철자를 의미합니까? 나는 그것이 네임 스페이스 g에서 사용 된 것처럼 어디에서나 정규화 된 것을 볼 수 있지만 F :: n_s 초기화가 h에서 허용되는 이유나 왜 F :: n_s {h :: X :: k} 초기화가 추가 g :: 한정자없이 g 외부에서 허용됩니다. – Jeff

2

여기에서 핵심적인 혼란은 전문화에 관한 것이 아니라 자격에 관한 것입니다. 다음을 설명하는 마지막 전문화 (전역 네임 스페이스에서)를 살펴 보겠습니다.

template <> g::N g::F<float>::n_s{h::X::k}; 

줄이 시작되면 전역 네임 스페이스에 들어갑니다. 따라서 g::N은 반드시 g::F<float>과 같이 정규화 된 것입니다.

그러나 내가 전문화 한 것을 지나친 순간 (즉, n_s 이후) 이제는 전문화중인 범위 인 g::F에 있습니다. 추가 조회는이 범위 내에서 수행되므로 xh::X으로 규정되어야합니다.

그런데 원래 네임 스페이스를 둘러싸는 네임 스페이스에서 특수화 할 수 있지만 중첩 된 네임 스페이스 (귀하의 경우 h)를 전문적으로 처리 할 수는 있지만 이상하게 보입니다. 표준은 다소 모호합니다. 14.7.3/2 : "명시된 전문화는 전문 템플릿을 둘러싸는 네임 스페이스에서 선언되어야한다."

글로벌 네임 스페이스는 F을 포함하므로 괜찮습니다. g입니다. hF을 포함하지 않지만 hg에 해당하므로 전문화는 g 내에서 이루어 지므로 기술적으로 이점이 있습니다. 그러나 이러한 추론을 통해 모든 것을 묶는 전역 네임 스페이스 내부에 항상 있기 때문에 템플릿을 절대적으로 모든 곳에서 전문화 할 수 있습니다. 그래서 저는 GCC의 행동이 너무 관대하다는 것과 버그라고 확신합니다. 이것을 다른 컴파일러와 함께 시도한 다음 버그 또는 아마도 표준에 대한 결함 보고서를 제출해야합니다.

+0

감사합니다. 이것은 내가 뭘 의심했는지에 따라 다르지만, 스펙을 읽는 데있어서 직접적인 모순을 발견 할 수는 없습니다. h와 같은 중첩 된 네임 스페이스에 F와 같은 템플릿의 별명을 지정하려고 시도했지만, 위의 가장 평범한 사례/동작에 이르기까지 확장했습니다. – Jeff