Saya menyaksikan pembicaraan Walter Brown di Cppcon14 tentang pemrograman template modern ( Bagian I , Bagian II ) di mana ia mempresentasikan void_tteknik SFINAE- nya .
Contoh:
Diberi templat variabel sederhana yang mengevaluasi voidjika semua argumen templat terbentuk dengan baik:
template< class ... > using void_t = void;
dan sifat berikut yang memeriksa keberadaan variabel anggota yang disebut anggota :
template< class , class = void >
struct has_member : std::false_type
{ };
// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
Saya mencoba memahami mengapa dan bagaimana ini bekerja. Karena itu contoh kecil:
class A {
public:
int member;
};
class B {
};
static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );
1. has_member< A >
has_member< A , void_t< decltype( A::member ) > >A::memberadadecltype( A::member )terbentuk dengan baikvoid_t<>valid dan dievaluasi untukvoid
has_member< A , void >dan karena itu memilih templat khusushas_member< T , void >dan mengevaluasi ketrue_type
2. has_member< B >
has_member< B , void_t< decltype( B::member ) > >B::membertidak adadecltype( B::member )berbentuk buruk dan gagal diam-diam (sfinae)has_member< B , expression-sfinae >jadi templat ini dibuang
- kompiler ditemukan
has_member< B , class = void >dengan void sebagai argumen default has_member< B >mengevaluasi kefalse_type
Pertanyaan:
1. Apakah pemahaman saya tentang ini benar?
2. Walter Brown menyatakan bahwa argumen default haruslah tipe yang sama persis seperti yang digunakan void_tagar bisa berfungsi. Mengapa demikian? (Saya tidak mengerti mengapa jenis ini harus cocok, bukankah sembarang jenis standar berfungsi?)
has_member< T , class = void >defaulting void. Dengan asumsi sifat ini hanya akan digunakan dengan 1 argumen templat kapan saja, maka argumen default dapat berupa jenis apa saja?
template <class, class = void>menjadi template <class, class = void_t<>>. Jadi sekarang kita bebas untuk melakukan apa pun yang kita inginkan dengan void_timplementasi template alias :)
has_member<A,int>::value. Kemudian, spesialisasi parsial yang mengevaluasihas_member<A,void>tidak dapat cocok. Oleh karena itu, perluhas_member<A,void>::value, atau, dengan gula sintaksis, argumen tipe defaultvoid.