4

P0091r3 (현재 C++ 초안 표준 인 N4606에 채택 된 "클래스 템플릿에 대한 템플릿 인수 차감"용지)을 이해하려고합니다.C++에서 클래스 템플릿 인수 공제에 대한 질문 17

나는 나는 그것이 템플릿 이름은 하나의 템플릿을 식별하는 가장 간단한 경우, 작동 방법을 이해 믿습니다

template<class T> 
struct S { 
    S(T); 
    S(const std::vector<T>&); 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto s = S(v); 
} 

S는 기본 템플릿을 식별를, 그래서 우리는 구성된 가상의 과부하 세트를 만들

template<class T> void Sctor(T); 
template<class T> void Sctor(const std::vector<T>&); 

과 가상 통화 오버로드 확인을 수행

Sctor(v) 

이 경우 우리는 가상의 Sctor(const std::vector<T>&) [with T=int]을 호출하기로 결정했습니다. 결국 우리는 S<int>::S(const std::vector<int>&)이라고 부르며 모든 것이 훌륭하게 작동한다는 것을 의미합니다.

이해가 안되는 부분은 부분 특수화가있는 상태에서 이것이 작동하는 방식입니다.

template<class T> 
struct S { 
    S(T); 
}; 

template<class T> 
struct S<std::list<T>> { 
    S(const std::vector<T>&); 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto s = S(v); 
} 

은 우리가 직관적으로 여기를 원하는 것은 S<std::list<int>>::S(const std::vector<int>&)를 호출합니다. 그건 우리가 실제로 얻는 것입니까? 이 부분은 어디에 지정되어 있습니까?

기본적으로 나는 직관적으로 P0091r3 "는 템플릿 이름에 의해 지정된 클래스 템플릿"에 의해 무엇을 의미하는지 이해가 안

: 그건 기본 템플릿을 의미 하는가, 또는 그것뿐만 아니라 모든 부분 전문화 및 명시 적 전체 전문 포함되어 있습니까?

는 (나는 또한 §7.1.6.2p2에 P0091r3의 변경은

template<class T> 
struct iterator { 
    iterator& operator++(int) { 
     iterator result = *this; // injected-class-name or placeholder? 
     //... 
    } 
}; 

주입 수준의 이름을의를 사용하여 암호를 해독하지 않는 방법을 이해하지 않습니다하지만 완전히 다른 질문입니다. -fconcepts이 같은)


클래스 템플릿 공제 및 명시 적으로 공제 가이드), 아마도 -f 깃발 아래 연타 나 GCC (의 현존 버전에서 지원하고 있습니까? 만약 그렇다면, 나는 현실에서 이러한 예들 중 일부를 가지고 놀 수 있었고 아마 혼란의 절반을 정리할 수 있었다.

+0

현재 주요 컴파일러 (아마도 컴파일러가 전혀 없음)는 생성자에 대한 템플릿 인수 공제를 지원하지 않습니다. 필자가 잘못 생각하지 않는다면 어딘가에서 구현 환경을 수집하는 데 사용 된 Clang 브랜치가있을 수 있지만 온라인에서도 사용할 수 있는지조차 확신 할 수 없습니다. – Morwenn

답변

1

나는 현재 P0091의 문구가 이와 관련하여 적합하지 않다고 말하고 싶다. 기본 클래스 템플릿인지 여부 또는 모든 전문 분야의 생성자를 포함하는지 여부를 명확히해야합니다.

내가 말했듯이, P0091의 의도은 부분 전문화가 인수 공제에 참여하지 않는다고 생각합니다. 이 기능은 컴파일러가 클래스의 템플릿 인수가 무엇인지 결정할 수있게합니다. 그러나 부분 전문화를 선택하는 것은 해당 템플릿 인수가 실제로 무엇인지입니다. S<std::list<T>> 특수화를 얻는 방법은 템플릿 인수 목록에 std::listS으로 사용하는 것입니다.

특정 매개 변수가 특정 전문화를 사용하게하려면 공제 안내서를 사용해야합니다. 그것은 결국 그들이 무엇을위한 것입니다.

2

이것은 약간의 제안으로 넘어졌지만, 기본 클래스 템플릿의 생성자 만 고려할 것이라고 생각합니다. 우리가 "는"클래스 템플릿에 대해 얘기하는 경우

  • For each constructor of the class template designated by the template-name, a function template with the following properties is a candidate: [...]

,이 특히 클래스 템플릿 부분을 같이 기본 클래스 템플릿입니다 : 이것에 대한 증거는 새로운 [class.template.deduction]가 가지고 있다는 것입니다 이름 조회 ([temp.class.spec]/6)로 전문화를 찾을 수 없습니다. 또한 프로토 타입 구현 (아래 참조)이 작동하는 것처럼 보입니다.

이 문서에서 클래스 템플릿 부분 특수화는 "암시 적 차감 가이드의 장단점"섹션에서 다루지 만 기본 클래스 템플릿 내의 생성자가 경성 (SFINAE가 아닌) 오류를 유발할 수 있다는 우려는 없습니다.

template<class T> struct X { 
    using ty = T::type; 
    static auto foo() { return typename T::type{} }; 
    X(ty); #1 
    X(decltype(foo())); #2 
    X(T); 
}; 
template<class T> 
struct X<T*> { 
    X(...); 
}; 
X x{(int *)0}; 
클래스 템플릿 부분 특수화 생성자에 대한 귀하의 호소가 고려해야 할

는 그것의 얼굴에 합리적이지만 모호성을 초래할 수 있습니다 :

template<class T> struct Y { Y(T*); }; 
template<class T> struct Y<T*> { Y(T*); }; 
Y y{(int*) 0}; 

그것은 아마도 바람직 할 것 클래스 템플리트의 특수화를 통해 (클래스 분류기로서) 순위가 정해지는 차감 안내서를 내재적으로 생성했습니다.

프로토 타입 구현을 시험해 보려면 제작자가 clang의 지점을 github : https://github.com/faisalv/clang/tree/clang-ctor-deduction에 게시했습니다.


논문 ("주입 된 클래스 이름에 대한 참고 사항")은 주입 된 클래스 이름이 템플릿 이름보다 우선한다는 것을 나타냅니다. 문안은 다음을 보장하기 위해 추가됩니다 :

The template-name shall name a class template that is not an injected-class-name.

+0

다시 삽입 된 클래스 이름 : 그 문장을 보았지만 "* 템플릿 이름 *이 * injection-class-name *이거나 프로그램이 잘못되었습니다." "여는 괄호 뒤에 오는 * * template-name *은 결코 * injected-class-name *"으로 해석되지 않습니다. ... 사실, 당신의 해석 ("* 템플릿 - 이름 *은 가능한 한 언제라도 * 주사 - 클래스 - 이름 *으로 해석되어야한다")은 나의 것과 정확히 반대입니다! : P – Quuxplusone

+0

@Quuxplusone [temp.local]/1 injection-class-name이 * template-name *으로 처리 될 때 열거됩니다. –

관련 문제