Pertimbangkan program berikut.
#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 );
}
Program berhasil dikompilasi dan hasilnya adalah
g( 42 );
Sekarang mari kita ganti nama fungsi non-templat g
menjadi 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 );
}
Sekarang program tidak dikompilasi oleh gcc HEAD 10.0.0 20200 dan clang HEAD 10.0.0 tetapi berhasil dikompilasi oleh Visual C ++ 2019 ..
Sebagai contoh, compiler gcc mengeluarkan set pesan berikut.
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 )
| ~~~~^
Maka muncul pertanyaan: haruskah kode dikompilasi dan apa alasannya kode tersebut tidak dikompilasi oleh gcc dan dentang?
c++
templates
language-lawyer
c++17
template-argument-deduction
Vlad dari Moskow
sumber
sumber
g
(alih-alih&g
) ke templat fungsi menyebabkan peluruhan tipe (referensi nilai fungsi meluruh ke penunjuk ke fungsi:void(&)(T)
=>void(*)(T)
). Konversi tersirat ini terjadi karena tidak adaf
kelebihan lainnya dengan kecocokan yang lebih baik. Pada contoh kedua, ada ambiguitas yangf
ingin Anda panggil karena ... tidak tahu yang manaf
argumennya.Jawaban:
Sepertinya saya bahwa gcc dan dentang benar. Ini seharusnya tidak dikompilasi. Parameter fungsi dari mana Anda ingin
T
dideduksi menjadi konteks non-deduksi di sini saat argumen yang diberikan adalah kumpulan kelebihan yang berisi templat fungsi [temp.deduct.type] /5.5 :Dengan demikian,
T
tidak dapat disimpulkan dan kelebihan lainnya tidak layak karena tidak ada konversi; persis apa yang dikatakan gcc ...sumber
Ini adalah dua fungsi kelebihan beban dan fungsi non-templat harus dipilih dibandingkan dengan fungsi templated, jadi f (int x) dipilih maka melewati fungsi sebagai argumen dalam fungsi yang int harus dilewati adalah mustahil. dan di bawah ini akan berfungsi. Terima kasih
sumber
void f<int>(void(int))
dihasilkan untuk melakukan resolusi kelebihan pada kedua level.