Sesuatu yang saya temukan sering saya lakukan belakangan ini adalah menyatakan typedefs relevan dengan kelas tertentu di dalam kelas itu, yaitu
class Lorem
{
typedef boost::shared_ptr<Lorem> ptr;
typedef std::vector<Lorem::ptr> vector;
//
// ...
//
};
Jenis-jenis ini kemudian digunakan di tempat lain dalam kode:
Lorem::vector lorems;
Lorem::ptr lorem( new Lorem() );
lorems.push_back( lorem );
Alasan saya menyukainya:
- Ini mengurangi kebisingan yang diperkenalkan oleh templat kelas,
std::vector<Lorem>
menjadiLorem::vector
, dll. - Ini berfungsi sebagai pernyataan niat - dalam contoh di atas, kelas Lorem dimaksudkan untuk menjadi referensi yang dihitung melalui
boost::shared_ptr
dan disimpan dalam vektor. - Hal ini memungkinkan implementasi untuk berubah - yaitu jika Lorem perlu diubah untuk menjadi referensi intrusively dihitung (via
boost::intrusive_ptr
) pada tahap selanjutnya maka ini akan memiliki dampak minimal pada kode. - Saya pikir ini terlihat lebih cantik dan lebih mudah dibaca.
Alasan saya tidak menyukainya:
- Kadang-kadang ada masalah dengan dependensi - jika Anda ingin menanamkan, katakanlah,
Lorem::vector
dalam kelas lain tetapi hanya perlu (atau ingin) untuk meneruskan mendeklarasikan Lorem (sebagai lawan memperkenalkan dependensi pada file header-nya) maka Anda akhirnya harus menggunakan tipe eksplisit (misalnya,boost::shared_ptr<Lorem>
bukanLorem::ptr
), yang sedikit tidak konsisten. - Mungkin tidak terlalu umum, dan karenanya lebih sulit untuk dipahami?
Saya mencoba untuk bersikap objektif dengan gaya pengkodean saya, jadi akan lebih baik untuk mendapatkan beberapa pendapat lain tentangnya sehingga saya dapat membedah pemikiran saya sedikit.
c++
coding-style
typedef
Will Baker
sumber
sumber
Inilah tepatnya yang tidak dilakukannya.
Jika saya melihat 'Foo :: Ptr' dalam kode, saya sama sekali tidak tahu apakah itu shared_ptr atau Foo * (STL memiliki :: pointer typedefs yang T *, ingat) atau apa pun. Esp. jika itu adalah pointer bersama, saya tidak memberikan typedef sama sekali, tetapi tetap menggunakan shared_ptr secara eksplisit dalam kode.
Sebenarnya, saya jarang menggunakan typedef di luar Template Metaprogramming.
Desain STL dengan konsep yang didefinisikan dalam hal fungsi anggota dan typedef bersarang adalah cul-de-sac historis, pustaka templat modern menggunakan kelas fungsi dan sifat-sifat gratis (lihat Boost.Graph), karena ini tidak mengecualikan tipe bawaan dari memodelkan konsep dan karena itu membuat mengadaptasi jenis-jenis yang tidak dirancang dengan konsep templat perpustakaan yang diberikan dalam pikiran lebih mudah.
Jangan menggunakan STL sebagai alasan untuk membuat kesalahan yang sama.
sumber
std::allocator_traits<Alloc>
kelas baru ... Anda tidak perlu mengkhususkannya untuk setiap pengalokasi tunggal yang Anda tulis, karena hanya meminjam jenis langsung dariAlloc
.Alloc
penulis, tidaklah terlalu sulit untuk mengkhususkanstd::allocator_traits<>
pada tipe barunya daripada menambahkan typedef yang diperlukan. Saya juga mengedit jawabannya, karena jawaban lengkap saya tidak cocok dengan komentar.allocator_traits
mencoba untuk membuat pengalokasi kustom, saya tidak perlu repot-repot dengan lima belas anggota kelas ciri-ciri ... semua harus saya lakukan adalah mengatakantypedef Blah value_type;
dan memberikan fungsi anggota yang sesuai, dan defaultallocator_traits
akan mencari tahu beristirahat. Selanjutnya, lihat contoh Boost.Graph Anda. Ya, itu membuat penggunaan kelas-kelas sifat ... tetapi implementasi defaultgraph_traits<G>
hanya queryG
untuk typedefs internal sendiri.iterator_traits
kelas sehingga algoritma umum Anda dapat dengan mudah meminta informasi yang sesuai. Yang, lagi-lagi, default untuk menanyakan iterator untuk informasinya sendiri. Panjang dan pendeknya adalah bahwa ciri dan typedef internal hampir tidak eksklusif ... mereka saling mendukung.iterator_traits
menjadi perlu karenaT*
harus menjadi modelRandomAccessIterator
, tetapi Anda tidak dapat memasukkan typedef yang diperlukan ke dalamT*
. Setelah ituiterator_traits
, typedef bersarang menjadi mubazir, dan saya berharap mereka telah dihapus di sana dan kemudian. Untuk alasan yang sama (ketidakmungkinan untuk menambahkan typedef internal),T[N]
tidak memodelkanSequence
konsep STL , dan Anda memerlukan kludges sepertistd::array<T,N>
. Boost.Range menunjukkan bagaimana konsep Sequence modern dapat didefinisikan yangT[N]
dapat memodelkan, karena tidak memerlukan typedef bersarang, atau fungsi anggota.Typedef adalah yang berdasarkan desain dan sifat berbasis kebijakan di C ++, jadi Kekuatan Pemrograman Generik dalam C ++ berasal dari typedefs sendiri.
sumber
Typdefs jelas merupakan gaya yang baik. Dan semua "alasan saya suka" Anda baik dan benar.
Tentang masalah yang Anda miliki dengan itu. Deklarasi maju bukanlah cawan suci. Anda cukup mendesain kode Anda untuk menghindari ketergantungan multi level.
Anda dapat memindahkan typedef di luar kelas tetapi Class :: ptr jauh lebih cantik daripada ClassPtr sehingga saya tidak melakukan ini. Seperti halnya ruang nama bagi saya - hal-hal tetap terhubung dalam ruang lingkup.
Terkadang saya melakukannya
Dan itu bisa menjadi standar untuk semua kelas domain dan dengan beberapa spesialisasi untuk yang tertentu.
sumber
STL melakukan hal semacam ini sepanjang waktu - typedefs adalah bagian dari antarmuka untuk banyak kelas di STL.
semua typedef yang merupakan bagian dari antarmuka untuk berbagai kelas template STL.
sumber
Pilihan lain untuk ini adalah ide yang bagus. Saya mulai melakukan ini ketika menulis simulasi yang harus efisien, baik dalam waktu maupun ruang. Semua tipe nilai memiliki Ptr typedef yang dimulai sebagai penambah shared pointer. Saya kemudian melakukan beberapa profil dan mengubah beberapa dari mereka untuk meningkatkan pointer yang mengganggu tanpa harus mengubah salah satu kode di mana objek-objek ini digunakan.
Perhatikan bahwa ini hanya berfungsi ketika Anda tahu di mana kelas akan digunakan, dan bahwa semua penggunaan memiliki persyaratan yang sama. Saya tidak akan menggunakan ini dalam kode perpustakaan, misalnya, karena Anda tidak bisa tahu kapan menulis perpustakaan konteks di mana ia akan digunakan.
sumber
Saat ini saya sedang mengerjakan kode, yang secara intensif menggunakan jenis typedef ini. Sejauh ini tidak masalah.
Tapi saya perhatikan bahwa ada cukup sering mengetik berulang, definisi dibagi di antara beberapa kelas, dan Anda tidak pernah benar-benar tahu jenis apa yang Anda hadapi. Tugas saya adalah merangkum ukuran beberapa struktur data kompleks yang tersembunyi di balik typedefs ini - jadi saya tidak bisa mengandalkan antarmuka yang ada. Dalam kombinasi dengan tiga hingga enam tingkat ruang nama bersarang dan kemudian menjadi membingungkan.
Jadi sebelum menggunakannya, ada beberapa hal yang perlu diperhatikan
sumber
Saya merekomendasikan untuk memindahkan typedef tersebut di luar kelas. Dengan cara ini, Anda menghapus ketergantungan langsung pada pointer bersama dan kelas vektor dan Anda bisa memasukkannya hanya saat diperlukan. Kecuali Anda menggunakan tipe-tipe itu dalam implementasi kelas Anda, saya menganggap mereka tidak boleh menjadi typedef dalam.
Alasan Anda menyukainya masih cocok, karena dipecahkan oleh tipe aliasing melalui typedef, bukan dengan mendeklarasikannya di dalam kelas Anda.
sumber
Ketika typedef hanya digunakan di dalam kelas itu sendiri (yaitu dinyatakan sebagai pribadi) saya pikir itu ide yang bagus. Namun, untuk alasan tepat yang Anda berikan, saya tidak akan menggunakannya jika typedef perlu diketahui di luar kelas. Dalam hal ini saya merekomendasikan untuk memindahkan mereka di luar kelas.
sumber