[c++] 함수 유형의 인수에 대한 템플리트 인수 공제

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

#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이 코드를 컴파일하지 않는 이유는 무엇입니까?



답변

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

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

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

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

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


답변

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

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

  int main(){

     f( f );
  }


답변