함수 유형의 인수에 대한 템플리트 인수 공제


10

다음 프로그램을 고려하십시오.

#include <iostream>

template <typename T>
void f( void ( *fn )( T ) )
{
    fn( 42 );
}

void g( int x )
{
    std::cout << "g( " << x << " );\n";
}

int main()
{
    f( g );
}

프로그램이 성공적으로 컴파일되고 출력이

g( 42 );

이제 비 템플릿 함수의 이름을 변경하자 g에를 f.

#include <iostream>

template <typename T>
void f( void ( *fn )( T ) )
{
    fn( 42 );
}

void f( int x )
{
    std::cout << "f( " << x << " );\n"; 
}

int main()
{
    f( f );
}

이제 프로그램은 gcc HEAD 10.0.0 20200 및 clang HEAD 10.0.0에 의해 컴파일되지 않았지만 Visual C ++ 2019에 의해 성공적으로 컴파일되었습니다.

예를 들어, 컴파일러 gcc는 다음 메시지 세트를 발행합니다.

prog.cc: In function 'int main()':
prog.cc:22:10: error: no matching function for call to 'f(<unresolved overloaded function type>)'
   22 |     f( f );
      |          ^
prog.cc:4:6: note: candidate: 'template<class T> void f(void (*)(T))'
    4 | void f( void ( *fn )( T ) )
      |      ^
prog.cc:4:6: note:   template argument deduction/substitution failed:
prog.cc:22:10: note:   couldn't deduce template parameter 'T'
   22 |     f( f );
      |          ^
prog.cc:14:6: note: candidate: 'void f(int)'
   14 | void f( int x )
      |      ^
prog.cc:14:13: note:   no known conversion for argument 1 from '<unresolved overloaded function type>' to 'int'
   14 | void f( int x )
      |         ~~~~^

따라서 질문이 발생합니다. 코드를 컴파일해야하고 gcc 및 clang이 코드를 컴파일하지 않는 이유는 무엇입니까?



참고 : 첫 번째 예제에서 g(대신 &g)를 함수 템플릿에 전달하면 형식이 소멸됩니다 (함수 lvalue 참조는 함수에 대한 포인터로 소멸됩니다 : void(&)(T)=> void(*)(T)). 이 암시 적 변환 f은 더 일치하는 다른 과부하 가 없기 때문에 발생합니다 . 두 번째 예에는 f실제로 호출하려는 모호성이 있습니다. 왜냐하면 f어느 쪽이 인수 인지 알 수 없기 때문 입니다.
Xeverous

답변:


7

gcc와 clang이 올바른 것 같습니다. 컴파일해서는 안됩니다. 원하는 함수 매개 변수T제공된 인수가 함수 템플릿 [temp.deduct.type] /5.5 를 포함하는 과부하 세트가되는 순간 여기서 추론 는 비 감소 된 컨텍스트가됩니다 .

교육을받지 않은 상황은 다음과 같습니다.

  • […]
  • 연관된 함수 인수가 함수이거나 오버로드 된 함수 세트 ([over.over])이고 인수 중 하나 이상이 적용되므로 인수 공제를 수행 할 수없는 함수 매개 변수입니다.

    • […]
    • 인수로 제공된 함수 세트에는 하나 이상의 함수 템플리트가 있습니다.
  • […]

따라서 T추론 할 수없고 변환이 없기 때문에 다른 과부하를 실행할 수 없습니다. 정확히 gcc의 말…


0

이것들은 두 개의 오버로드 된 함수이며 템플릿이 아닌 함수는 템플릿 함수와 비교하여 선택해야하므로 f (int x)가 선택되었으므로 int를 전달 해야하는 함수의 인수로 함수를 전달하는 것은 불가능합니다. 아래가 작동해야합니다. 감사

void f( void ( *fn )( int ) ){
  fn( 42 );
}
void f( int x ){
    std::cout << "f( " << x << " );\n";
  }

  int main(){

     f( f );
  }

템플릿 이외의 기능은 과부하 해결 중에 동점이있는 경우에만 선호됩니다. 질문의 코드는 그 시점에 도달하지 못합니다 . 어느 수준 에서든void f<int>(void(int)) 과부하 해결을 수행하기 위해 생성 된 전문화는 없습니다 .
Davis Herring
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.