निम्नलिखित कार्यक्रम पर विचार करें।
#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 और क्लैंग HEAD 10.0.0 द्वारा संकलित नहीं किया गया है, लेकिन विजुअल C ++ +9 ।।
उदाहरण के लिए कंपाइलर 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
) एक प्रकार के क्षय का कारण बनता है (एक फंक्शन के लिए पॉइंटर को रेवल्यू रेफरेंस डिसेबल करता है: void(&)(T)
=> void(*)(T)
)। यह अंतर्निहित रूपांतरण इसलिए होता है क्योंकि f
बेहतर मैच के साथ कोई अन्य अधिभार नहीं होता है । दूसरे उदाहरण में, एक अस्पष्टता है जिसे f
आप वास्तव में कॉल करना चाहते हैं क्योंकि ... यह नहीं जानता कि कौन सा f
तर्क है।