다음 프로그램을 고려하십시오.
#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 );
}