Mengapa Fungsi Gagal dan Cara Menyelesaikan Isu
Kod yang disediakan cuba mencipta fungsi generik yang boleh mencetak kedua-dua tindanan dan baris gilir . Walau bagaimanapun, ia gagal disebabkan oleh isu asas: kedua-dua cabang pernyataan if-else mesti boleh dikompilasi. Dalam kes ini, mereka tidak.
Ralat berlaku secara khusus kerana fungsi ahli top() hanya tersedia untuk tindanan, manakala fungsi ahli front() hanya tersedia untuk baris gilir. Pengkompil membenderakan masalah apabila cuba menyusun kedua-dua cawangan untuk jenis bekas yang sama, kerana ia tidak dapat menentukan fungsi ahli yang hendak digunakan.
Satu penyelesaian kepada masalah ini ialah menggunakan pengkhususan separa. Pengkhususan separa membolehkan anda menentukan pelaksanaan templat yang berbeza untuk jenis atau kelas tertentu. Dalam kes ini, anda boleh menentukan pengkhususan separa untuk tindanan dan baris gilir, memastikan setiap pelaksanaan mempunyai fungsi ahli yang sesuai:
<code class="cpp">template <typename Cont> struct element_accessor; template <typename T> struct element_accessor<std::stack<T>> { const T& operator()(const std::stack<T>& s) const { return s.top(); } }; template <typename T> struct element_accessor<std::queue<T>> { const T& operator()(const std::queue<T>& q) const { return q.front(); } }; template<typename Cont> void print_container(Cont& cont){ while(!cont.empty()){ auto elem = element_accessor<Cont>{}(cont); std::cout << elem << '\n'; cont.pop(); } }
Penyelesaian ini menggunakan element_accessor kelas untuk mengakses fungsi ahli yang sesuai untuk setiap jenis kontena. Dengan menyediakan pengkhususan separa untuk tindanan dan baris gilir, anda memastikan bahawa kod yang betul disusun untuk setiap kes.
Penyelesaian lain, tersedia dalam C 17 dan kemudian, adalah menggunakan jika constexpr:
<code class="cpp">template<template<class> typename Cont, typename T> void print_container(Cont<T>& cont){ while(!cont.empty()){ if constexpr (std::is_same_v<Cont<T>, std::stack<T>>) std::cout << cont.top() << '\n'; else if constexpr (std::is_same_v<Cont<T>, std::queue<T>>) std::cout << cont.front() << '\n'; cont.pop(); } }</code>
Penyelesaian ini menggunakan ungkapan bersyarat constexpr untuk memilih kod yang betul berdasarkan jenis bekas. Dengan menyemak jenis Cont pada masa penyusunan, anda boleh memastikan bahawa fungsi ahli yang betul dipanggil untuk setiap bekas.
Atas ialah kandungan terperinci Mengapa Fungsi Generik Saya untuk Timbunan Cetakan dan Baris Gilir Gagal, dan Bagaimana Saya Boleh Membetulkannya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!