문제

또 다른 질문을 읽는 동안 부분 순서에 문제가 생겼습니다.

template<typename T>
struct Const { typedef void type; };

template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1

template<typename T>
void f(T, void*) { cout << "void*"; } // T2

int main() {
  // GCC chokes on f(0, 0) (not being able to match against T1)
  void *p = 0;
  f(0, p);
}

두 기능 템플릿의 경우 과부하 분해능을 입력하는 전문화의 기능 유형은 다음과 같습니다. void(int, void*). 그러나 부분 순서 (Comeau 및 GCC에 따르면)는 이제 두 번째 템플릿이 더 특화되어 있다고 말합니다. 하지만 왜?

부분 주문을 거쳐 질문이있는 곳을 보여 드리겠습니다. 5월 Q 에 따라 부분 순서를 결정하는 데 사용되는 고유 한 메이크업 유형입니다. 14.5.5.2.

  • 변환 된 매개 변수 목록 T1 (Q 삽입) : (Q, typename Const<Q>::type*). 논쟁의 유형은 다음과 같습니다 AT = (Q, void*)
  • 변환 된 매개 변수 목록 T2 (Q 삽입) : BT = (Q, void*), 또한 인수의 유형이기도합니다.
  • 변환되지 않은 매개 변수 목록 T1: (T, typename Const<T>::type*)
  • 변환되지 않은 매개 변수 목록 T2: (T, void*)

C ++ 03은 이것을 지정하기 때문에 여러 결함 보고서에서 읽은 의도를 사용했습니다. 위의 변환 된 매개 변수 목록 T1 (라고 불리는 AT 나에 의해)는 인수 목록으로 사용됩니다 14.8.2.1 "함수 호출에서 템플릿 인수 추론".

14.8.2.1 변환 할 필요가 없습니다 AT 또는 BT 더 이상 자체 (예 : 참조 선언자 제거 등) 14.8.2.4, 각각 독립적으로 A / P 쌍은 유형 공제를합니다.

  • AT 에 맞서 T2: { (Q, T), (void*, void*) }. T 여기에 유일한 템플릿 매개 변수이며 T 해야합니다 Q. 유형 공제는 사소한 성공을 거두었습니다 AT 에 맞서 T2.

  • BT 에 맞서 T1: { (Q, T), (void*, typename Const<T>::type*) }. 그것은 그것을 찾을 것입니다 T ~이다 Q, 여기도 여기. typename Const<T>::type* 비정상적인 맥락이므로 아무것도 추론하는 데 사용되지 않습니다.


여기 내 첫 번째 질문이 있습니다. T 첫 번째 매개 변수에 대해 추론 되었습니까? 대답이 아니오 인 경우 첫 번째 템플릿이 더 전문적입니다. GCC와 Comeau는 두 번째 템플릿이 더 특화되어 있다고 말하면서 그들이 틀렸다고 생각하지 않기 때문에 이것은 사실이 아닙니다. 그래서 우리는 "예"를 가정하고 삽입합니다 void* ~ 안으로 T. 단락 (14.8.2.4) 말한다 "공제는 각 쌍에 대해 독립적으로 수행되며 결과는 결합됩니다." 그리고 또한 "특정 상황에서는 값이 유형 공제에 참여하지 않고 대신 다른 곳에서 추론되거나 명시 적으로 지정된 템플릿 인수의 값을 사용합니다." 이것은 "예"처럼 들립니다.

따라서 모든 A / P 쌍에 대해 공제도 성공합니다. 이제 각 템플릿은 적어도 다른 템플릿만큼 전문화되어 있습니다. 공제는 암시 적 변환에 의존하지 않았고 양방향으로 성공했기 때문입니다. 결과적으로 호출은 모호해야합니다.

두 번째 질문 : 이제 구현에서 두 번째 템플릿이 더 전문적이라고 말하는 이유는 무엇입니까? 내가 간과 한 요점은 무엇입니까?


편집하다: 나는 최근의 GCC 버전에서 명시 적 전문화와 인스턴스화를 테스트했습니다.4.4) 전문화에 대한 언급은 모호하며 이전 버전의 GCC (GCC) (4.1) 모호성 오류가 발생하지 않습니다. 이는 최근 GCC 버전이 함수 템플릿에 대한 부분 순서가 일치하지 않음을 시사합니다.

template<typename T>
struct Const { typedef void type; };

template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1

template<typename T>
void f(T, void*) { cout << "void*"; } // T2

template<> void f(int, void*) { }
  // main.cpp:11: error: ambiguous template specialization 
  // 'f<>' for 'void f(int, void*)'
도움이 되었습니까?

해결책

여기에 내가가요. 나는 동의한다 찰스 베일리 잘못된 단계는에서 나가는 것입니다 Const<Q>::Type* 에게 void*

template<typename T>
void f(T, typename Const<T>::type*) { cout << "Const"; } // T1

template<typename T>
void f(T, void*) { cout << "void*"; } // T2

우리가 취하고 싶은 단계는 다음과 같습니다.

14.5.5.2/2

두 개의 과부하 된 함수 템플릿이 주어지면, 하나는 다른 템플릿을 차례로 변환하고 인수 공제 (14.8.2)를 사용하여 다른 템플릿을 사용하여 결정할 수 있습니다.

14.5.5.2/3-b1

각각의 유형 템플릿 매개 변수에 대해, 고유 유형을 합성하고 함수 매개 변수 목록에서 해당 매개 변수의 각 발생 또는 템플릿 변환 함수에 대해 반환 유형에서 대체하십시오.

제 생각에는이 유형은 다음과 같이 합성됩니다.

(Q, Const<Q>::Type*)    // Q1
(Q, void*)              // Q2

나는 두 번째 합성 매개 변수를 요구하는 문구가 보이지 않습니다. T1 ~이다 void*. 나는 다른 맥락에서도 그에 대한 선례를 모른다. 유형 Const<Q>::Type* C ++ 유형 시스템 내에서 완벽하게 유효한 유형입니다.

이제 우리는 공제 단계를 수행합니다.

Q2 ~ T1

우리는 T1의 템플릿 매개 변수를 추론하려고합니다.

  • 매개 변수 1 : T 추론됩니다 Q
  • 매개 변수 2 : 비정상적인 컨텍스트

파라미터 2는 추론되지 않은 맥락이지만, 우리는 T에 대한 가치가 있기 때문에 여전히 공제가 성공했습니다.

Q1 ~ T2

T2의 템플릿 매개 변수를 추론합니다.

  • 매개 변수 1 : T 추론됩니다 Q
  • 매개 변수 2 : void* 일치하지 않습니다 Const<Q>::Type* 그래서 공제 실패.

IMHO, 표준이 우리를 실망시키는 곳이 있습니다. 매개 변수는 의존적이지 않기 때문에 어떤 일이 일어날 지 명확하지 않지만 (14.8.2.1/3의 끈적 끈적한 읽기를 기반으로) 매개 변수 유형 p가 의존하지 않는 경우에도 인수 유형 A가 일치해야한다는 것입니다. 그것.

T1의 합성 된 인수는 T2를 전문화하는 데 사용될 수 있지만 그 반대도 마찬가지는 아닙니다. 따라서 T2는 T1보다 전문화되어 있으며 최상의 기능도 마찬가지입니다.


UPDATE 1:

포옹을 덮기 위해 Const<Q>::type 무효. 다음 예를 고려하십시오.

template<typename T>
struct Const;

template<typename T>
void f(T, typename Const<T>::type*) // T1
{ typedef typename T::TYPE1 TYPE; }

template<typename T>
void f(T, void*)                    // T2
{ typedef typename T::TYPE2 TYPE ; }

template<>
struct Const <int>
{
  typedef void type;
};

template<>
struct Const <long>
{
  typedef long type;
};

void bar ()
{
  void * p = 0;
  f (0, p);
}

위에서 Const<int>::type 일반적인 오버로드 해상도 규칙을 수행 할 때 사용되지만 부분 오버로드 규칙에 도달 할 때는 사용되지 않습니다. 임의의 전문화를 선택하는 것은 옳지 않습니다. Const<Q>::type. 직관적이지는 않지만 컴파일러는 합성 된 형태의 형태를 갖는 것이 매우 기쁩니다. Const<Q>::type* 그리고 유형 공제 중에 사용합니다.


업데이트 2

template <typename T, int I>
class Const
{
public:
  typedef typename Const<T, I-1>::type type;
};

template <typename T>
class Const <T, 0>
{
public:
  typedef void type;
};

template<typename T, int I>
void f(T (&)[I], typename Const<T, I>::type*)     // T1
{ typedef typename T::TYPE1 TYPE; }

template<typename T, int I>
void f(T (&)[I], void*)                           // T2
{ typedef typename T::TYPE2 TYPE ; }


void bar ()
{
  int array[10];
  void * p = 0;
  f (array, p);
}

Const 템플릿은 일부 값으로 인스턴스화됩니다 I, 그것은 재귀 적으로 스스로를 인스턴스화 할 때까지 I 0에 도달합니다. 이것은 부분 전문화시기입니다 Const<T,0> 선택됩니다. 기능의 매개 변수에 대한 실제 유형을 종합하는 컴파일러가있는 경우 컴파일러가 배열 인덱스에 어떤 값을 선택합니까? 10시? 글쎄, 이것은 위의 예에서는 괜찮지 만 부분 전문화와 일치하지 않습니다. Const<T, 10 + 1> 그것은 적어도 개념적으로, 1 차의 무한한 수의 재귀 적 인스턴스화를 초래할 것이다. 선택한 값이 무엇이든 우리는 최종 조건을 해당 값 + 1으로 수정할 수 있으며 부분 순서 알고리즘에 무한 루프가 있습니다.

부분 순서 알고리즘이 어떻게 인스턴스화 될 수 있는지 알 수 없습니다. Const 무엇을 찾기 위해 type 정말로.

다른 팁

편집 : 공부 후 클랜의 부분 순서 알고리즘의 구현 (Doug Gregor)에서, 나는 원래 예제가 모호하지 않은 나머지 포스터에 동의하게되었습니다. 그러한 상황에서 발생해야합니다. 나는이 게시물을 편집하여 수정 된 생각을 나타냅니다 (내 자신의 이익 및 참조). 특히 Clang의 알고리즘은typename Const<T>::type'부분 순서 단계에서'void '로 번역되지 않으며 각 A/P 쌍은 서로 독립적으로 추론됩니다.

처음에 나는 왜 다음이 모호한 것으로 간주되는지 궁금했습니다.

        template<class T> void f(T,T*);  // 1

        template<class T> void f(T, int*); // 2

        f(0, (int*)0); // ambiguous

(The above is ambiguous because one cannot deduce f1(U1,U1*) from f2(T,int*), and going the other way, one cannot deduce f2(U2,int*) from f1(T,T*). Neither is more specialized.)

그러나 다음은 모호하지 않을 것입니다.

        template<class T> struct X { typedef int type; };
        template<class T> void f(T, typename X<T>::type*); // 3
        template<class T> void f(T, int*); // 2

(모호 할 것으로 예상 할 수있는 이유는 다음과 같은 일이 발생했을 경우입니다.
- f3(U1,X<U1>::type*) -> f3(U1, int*) ==> f2(T,int*) (deduction ok, T=U1)
- f2(U2,int*) ==> f3(T, X<T>::type*) (deduction ok, T=U2 makes X<U2>::type* -> int*)
이것이 사실이라면 어느 쪽도 다른 것보다 더 전문적이지 않을 것입니다.)

Clang의 부분 순서 알고리즘을 연구 한 후에는 마치 마치 마치 마치 '3'을 다음과 같이 취급하는 것이 분명합니다.

template<class T, class S> void f(T, S*); // 4

따라서 'typename x :: type'에 대한 독특한 'u'의 공제는 성공합니다 -

  • f3(U1,X<U1>::type*) is treated as f3(U1, U2*) ==> f2(T,int*) (deduction not ok)
  • f2(U2,int*) ==> f3(T,S* [[X<T>::type*]]) (deduction ok, T=U2, S=int)

그래서 '2'는 '3'보다 분명히 더 특화되어 있습니다.

t1에 대한 변환 된 매개 변수-목록 (q 삽입) : (q, typeName const :: type*). 인수의 유형은 at = (q, void*)입니다.

그것이 실제로 올바른 단순화인지 궁금합니다. 유형을 합성 할 때 Q, 당신은 Const 템플릿 종의 순서를 결정하기 위해?

template <>
struct Const<Q> { typedef int type; }

이것은 그것을 암시 할 것입니다 T2 적어도 전문화되지 않습니다 T1 a void* 매개 변수가 일치하지 않습니다 T1주어진 템플릿 매개 변수에 대한 두 번째 매개 변수.

편집 :이 게시물을 무시하십시오 - Doug Gregor가 구현 한 부분 주문을위한 Clangs 알고리즘을 연구 한 후 (이 글을 쓰는 시점에서 부분적으로 구현 되었음에도 불구하고 OP의 질문과 관련된 논리가 충분히 구현 된 것 같습니다) - IT. 마치 미지의 컨텍스트를 다른 템플릿 매개 변수로 취급하는 것처럼 보입니다. 명백한 무효* 인수가있는 오버로드는보다 전문화 된 버전이어야하며 모호성이 없어야합니다. 평소와 같이 comeau는 정확합니다. 이제이 행동을 명확하게 정의하는 표준의 문구에 관해서는 또 다른 문제입니다 ...

이 게시물은 comp.lang.c ++에 게시되었으므로 중재하고 혼란을 일으키고있는 것 같습니다. 여기에 해당 그룹에 대한 답을 게시 할 것이라고 생각했습니다. .

On Jul 25, 1:11 pm, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:

You are going one step too fast here. How do you know (and would the compiler know) that there is no specialisation of Const<Q> such that Const<Q>::type != void?

As far as I can see, the compiler would transform the parameter-list of A to: AT=(Q, <unknown>*). To call B with these parameters requires an implicit conversion (<unknown>* to void*) and therefore A is less specialised than B.

나는 이것이 틀렸다고 믿는다. 어떤 함수가 더 특화되어 있는지 확인할 때 (부분 주문 중) 컴파일러는 매개 변수 목록을 다음으로 변환합니다. (Q, void*) - 즉 실제로 관련 템플릿을 인스턴스화하고 (가장 잘 일치) '유형'의 값을 내부를 살펴 봅니다.이 경우 기본 템플릿을 기준으로 void*입니다.

부분 전문화에 관한 요점과 관련하여 - 템플릿이 다른 템플릿보다 더 전문화되는 것을 확인할 때, 사용할 수있는 유일한 유형은 고유 한 유형입니다. 끝났다) 그들은 고려 될 것이다. 나중에 추가하면 선택해야한다면 ODR을 위반하게됩니다 (14.7.4.1에 따라).

부분적/명시 적 전문화는 후보 세트를 형성하는 동안 고려를 얻을 것입니다. 그러나 이번에는 기능에 대한 실제 인수의 유형을 사용합니다. 가장 잘 어울리는 부분 전문화 (x)가 일부 매개 변수에 대해 더 나은 암시 적 변환 시퀀스를 갖는 함수 유형을 초래하면 부분 주문 단계로 만들지 않으며 "더 나은"기능이 선택됩니다 (만들기 전에 더 나은”기능이 선택됩니다. 부분 순서 단계에)

다음은 다양한 단계에서 무엇을 해야하는지에 대한 의견이있는 예입니다.

    template<class T, bool=true> struct X;  // Primary

    template<class T> struct X<T,true> { typedef T type; };  // A
    template<> struct X<int*,true> { typedef void* type; };  // B


    template<class T> void f(T,typename X<T>::type); //1
    template<class T> void f(T*,void*); //2


    int main()
    {
      void* pv;
      int* pi;


      f(pi,pi);   
      // two candidate functions: f1<int*>(int*,void*),  f2<int>(int*,void*)
      // Note: specialization 'B' used to arrive at void* in f1
      // neither has a better ICS than the other, so lets partially order
      // transformed f1 is f1<U1>(U1,X<U1,true>::type) --> f1<U1>(U1,U1) 
      //       (template 'A' used to get the second U1)
      // obviously deduction will fail (U1,U1) -> (T*,void*)
      // and also fails the other way (U2*, void*) -> (T,X<T>::type)
      // can not partially order them - so ambiguity 




      f(pv,pv);  
      // two candidate functions: f1<void*>(void*,void*), f2<void>(void*,void*)
      // Note: specialization 'A' used to arrive at second void* in f1
      // neither has a better ICS than the other, so lets partially order
      // transformed f1 is f1<U1>(U1,X<U1>::type) --> f1<U1>(U1,U1) 
      //       (template 'A' used to get the second U1)
      // obviously deduction will fail (U1,U1) -> (T*,void*)
      // and also fails the other way (U2*, void*) -> (T,X<T>::type)
      // can not partially order them - so ambiguity again             

    }

기본 템플릿에 정의가없는 경우 SFINAE가 부분 순서 단계에서 작동하며 다른 순서에서 추론 할 수 없으며 모호성이 발생해야한다는 점도 언급 할 가치가 있습니다.

또한 해당 함수 중 하나의 인스턴스화 지점이 번역 장치의 다른 곳으로 이동하면 다른 일치로 이어지는 다른 템플릿을 추가하면 ODR을 명확하게 위반하게됩니다.

On Jul 25, 1:11 pm, Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:

첫째,보다 전문화된다는 것은 이것을 의미합니다 보다 적은 오버로드 해상도로 해당 템플릿을 선택할 수있는 유형. 이것을 사용하면 부분 순서 규칙을 다음과 같이 요약 할 수 있습니다. A를 호출 할 수 있지만 B를 호출하지 않거나 과부하 해상도가 A를 호출하는 것을 선호하는 A에 대한 유형을 찾으십시오. 해당 유형을 찾을 수 있다면 B가 더 특수화됩니다. A.보다

여기에 논쟁이 없습니다. 그러나 현재의 규칙에 따라 OP의 예는 모호해야합니다.


마지막으로, Litb가 제기 한 두 가지 특정 질문에 대한 명백하고 명백한 답변이 있습니다.

1) 이것은 이제 첫 번째 매개 변수에 대해 추론 된 t 값을 사용합니까?
예 - 물론, 템플릿 인수 공제를 수행하고 있습니다. '링크'를 유지해야합니다.

2) 이제 구현이 왜 두 번째가 더 전문적이라고 말합니까?
그들이 틀렸기 때문에;)

나는 이것이 문제를 해결하기를 바랍니다. 아직 확실하지 않은 것이 있는지 알려주세요 :)

편집 : Litb는 그의 의견에서 좋은 점을 제기했습니다. 아마도 기본 템플릿이 항상 고유 한 생성 된 유형의 인스턴스화에 사용될 것이라고 진술 할 것입니다.
기본 템플릿이 호출되지 않는 인스턴스가 있습니다.
내가 얻는 것은 부분 순서가 발생할 때 일부 고유 한 생성 유형이 최고의 전문화와 일치하는 데 사용된다는 것입니다. 맞습니다. 기본 템플릿 일 필요는 없습니다. 위의 언어를 편집했습니다. 그는 또한 인스턴스화 지점 후 더 나은 일치하는 템플릿을 정의하는 것과 관련하여 문제를 제기했습니다. 그것은 인스턴스화 시점의 섹션에 따라 ODR을 위반하는 것입니다.


표준에 따르면 A/P 쌍이 생성되면 (Temp.Func.Order에 설명 된대로 변환 규칙을 사용하여) 템플릿 인수 공제 (Temp.deduct)를 사용하여 서로에 대해 추론하고 해당 섹션이 사례를 처리한다고 말합니다. 템플릿과 그 중첩 유형을 인스턴스화하여 인스턴스화 지점을 트리거하지 않은 컨텍스트. Temp.Point 섹션은 ODR 위반을 처리합니다 (부분 순서의 의미는 번역 단위 내에서 인스턴스화 지점에 관계없이 변경되지 않아야합니다). 혼란이 어디에서 왔는지 아직도 모르겠습니다. - Faisal Vali 1 시간 전 [이 의견 삭제

LITB : "q를 const :: 유형에 넣는 단계는 sfinae 규칙에 의해 명시 적으로 다루어지지 않습니다. sfinae 규칙은 인수 공제와 함께 작동하고 q를 함수 템플릿 함수 매개 변수 목록에 넣는 단락을 넣습니다. 14.5.5.2에서. '

sfinae 규칙은 여기서 사용되어야합니다. 어떻게 할 수 없습니까? 나는 그것이 충분히 암시된다고 생각합니다. 나는 그것이 더 명확해질 수 있다는 것을 부정하지 않을 것이며,위원회가 이것을 명확히하도록 권장하지만, 당신의 예를 충분히 해석하기 위해 명확하게 할 필요는 없다고 생각합니다.

연결하는 한 가지 방법을 제공하겠습니다. (14.8.2) : "명시 적 템플릿 인수 목록이 지정된 경우 템플릿 인수는 템플릿 매개 변수 목록과 호환되어야하며 아래에 설명 된대로 유효한 기능 유형을 초래해야합니다. 그렇지 않으면 유형 공제 실패"

(14.5.5.2/3)에서 "사용 된 변환은 다음과 같습니다. - 각 유형 템플릿 매개 변수에 대해, 고유 유형을 합성하고 함수 매개 변수 목록에서 해당 매개 변수의 각 발생 또는 템플릿 변환 함수에 대해 반환하는 것을 대체합니다. 유형."

내 생각에 위의 인용문은 각 템플릿 매개 변수에 대해 "고유 한 생성 유형"을 "작성"하면 함수 선언이 명시 적으로 기능 템플릿에 템플릿 인수로 고유 유형을 제공합니다. 이로 인해 잘못된 함수 유형이 발생하면 변환뿐만 아니라 더 중요한 것은 기능을 부분적으로 주문하는 데 필요한 후속 템플릿 인수 공제가 실패합니다.

(14.5.5.2/4)에서 "변환 된 함수 매개 변수 목록을 사용하여 다른 함수 템플릿에 대한 인수 공제를 수행하십시오. 변환 된 템플릿은 최소한 다른 것만 큼 특화되어 있습니다. 경우에만, 공제가 성공하고 추론 된 매개 변수 유형은 정확히 일치합니다 (따라서 공제는 암시 적 변환에 의존하지 않습니다). "

변환 된 기능 매개 변수 목록이 대체 실패로 이어지면 공제가 성공할 수 없다는 것을 알고 있습니다. 그리고 공제는 성공하지 못했기 때문에 다른 것만 큼 전문화되지는 않습니다. 이것이 우리가 부분적으로 주문하기 위해 알아야 할 전부입니다.

LITB :이 경우에 어떤 일이 일어나는지 잘 모르겠습니다. template<typename T> struct A; template<typename T> void f(T, typename A<T>::type); template<typename T> void f(T*, typename A<T>::type); 확실히, 그것은 유효한 코드로 지출되지만 :: 유형을 수행하면 템플릿 정의 컨텍스트에서 아직 정의되지 않았기 때문에 "또한"이런 종류의 대체로 인한 템플릿 인스턴스화에 대해 정의 된 POI가 없기 때문에 실패합니다. 순서를 결정하려고하는 동안 (부분 순서는 컨텍스트에 의존하지 않습니다. 관련된 두 기능 템플릿의 정적 속성입니다). 나는 이것이 수정해야 할 표준의 문제처럼 보인다고 생각합니다.

OK - 우리가 어디에서 다르게보고 있는지보고 있다고 생각합니다. 내가 당신을 올바르게 이해한다면, 당신은 이러한 함수 템플릿이 선언 될 때, 컴파일러는 오버로드 해상도가 그들 사이에서 선택되도록 트리거되는 것에 관계없이 그들 사이의 부분 순서를 추적하고 있다고 말합니다. 그것이 당신이 그것을 해석하는 방법이라면, 나는 당신이 설명하는 위의 행동을 기대하는 이유를 알 수 있습니다. 그러나 나는 표준이 그것을 요구하거나 의무화한다고 생각하지 않습니다.

이제 표준은 부분 순서가 함수를 호출하는 데 사용되는 유형에 비해 불가지론이라는 것이 명백합니다 (정적 속성이라고 설명 할 때 말하면 컨텍스트 독립이라고 생각합니다).

표준은 또한 과부하 해상도 (13.3.3/1) 과정에서 기능 템플릿간에 부분 순서 (부분 순서를 호출)에만 관심이 있음을 분명히합니다. 템플릿이고 다른 하나는 아닙니다. [클래스 템플릿의 부분 순서 부분 순서 부분 전문화는 별도의 문제이며 내 마음에는 해당 특정 클래스의 인스턴스화가 필요한 관련 컨텍스트 (기타 템플릿 정의)를 사용합니다.

따라서 내 생각에, 과부하 해상도가 수행 될 때 기능 템플릿의 부분 순서 기계가 호출되므로 과부하 해상도가 수행되는 시점에서 사용할 수있는 컨텍스트 (템플릿 정의 및 전문화)의 관련 부분을 사용해야합니다. .

따라서 상호 작용에 따라 위의 'Template Struct a'를 사용하는 예에 따라 코드가 유효합니다. 부분 순서는 정의 컨텍스트에서 수행되지 않습니다. 그러나 F (int*) 0,0)에 대한 호출을 작성하여 두 기능간에 과부하 해상도를 호출 할 경우 - 컴파일러가 후보 선언을 조립하거나 부분적으로 주문할 때 ( 부분 주문 단계에 도달)) 잘못된 표현식 또는 유형의 결과가 함수 유형의 일부로 결과가 우리를 도와주고 템플릿 공제가 실패한다는 것을 알려줍니다 (부분 순서가 관련이있는 한, 더 이상 할 수 없음을 의미합니다. 템플릿을 변환 할 수 없다면 다른 것보다 전문화).

이제 POI와 관련하여 - 당신이 내가 확신한다면, 내가 확신한다면, 변환 된 함수 유형은 명시 적으로 제공된 템플릿 인수 목록 (고유하게 생성 된 유형 사용)을 사용하여 암시 적 인스턴스화를 나타 내기 위해 다음 표준 따옴표가 관련이 있습니다.

14.6.4.1/1 함수 템플릿 전문화, 멤버 함수 템플릿 전문화 또는 클래스 템플릿의 멤 그것이 참조되는 컨텍스트는 템플릿 매개 변수에 따라 다르며, 전문화의 인스턴스화 지점은 동봉 된 전문화의 인스턴스화 지점입니다.

내가 이것을 해석하는 방식은 변환 된 함수 유형의 POI와 Origianl 함수 유형이 실제 함수 호출에 의해 생성 된 함수의 POI와 동일하다는 것입니다.

LITB : 부분 순서는 오히려 단지 전용입니다 a property of the syntactic form of parameters (i.e "T*" against "T(*)[N]"), 나는 사양을 수정하기 위해 투표합니다 (예 : "Q가 유형을 명명 한 자격을 갖춘 이름 지정자로 표시되면"Q "라는 유형이 다른 유형이 다른 고유 유형이라고 말합니다. This means that in template<typename T> void f(T, typename Const<T>::type*); the argument list is (Q, R*), for example. Same for template<typename T> void f(T*, typename ConstI<sizeof(T)>::type); the arg lisst would be (Q*, R). A similar rule would be needed for non-type parameters, of course.그래도이 문제에 대해 생각하고 몇 가지 테스트 사례를 만들어 자연 순서를 산출 할 것인지 확인해야합니다.

AAH- 이제 당신은 우리 모두가 직관적으로 기대하는 것에 찬성하여 모호성을 해결하는 가능한 솔루션을 제안하고 있습니다. 이것은 별도의 문제입니다. 그리고 당신이 향하는 방향을 좋아하지만, 나는 또한 생각을해야 할 것입니다. 그것의 효과를 선포하기 전에 그것에.

토론을 계속 해주셔서 감사합니다. 나는 당신이 댓글을 작성하는 데 제한하지 않기를 바랍니다.

내 게시물을 편집 할 수 있으므로 더 쉬운 경우 게시물 내에서 자유롭게 응답하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top