Cukup jelas.
Pada dasarnya, katakan saya memiliki daftar jenis seperti:
using type_list_1 = type_list<int, somestructA>;
using type_list_2 = type_list<somestructB>;
using type_list_3 = type_list<double, short>;
Mereka bisa menjadi nomor variadic dari daftar jenis.
Bagaimana cara saya mendapatkan daftar produk Cartesian?
result = type_list<
type_list<int, somestructB, double>,
type_list<int, somestructB, short>,
type_list<somestructA, somestructB, double>,
type_list<somestructA, somestructB, short>
>;
Saya mencoba-coba tentang cara membuat produk Cartesian dua arah seperti yang diberikan di sini: Bagaimana cara membuat produk Cartesian dari daftar jenis? , tapi n jalan sepertinya tidak begitu sepele.
Untuk saat ini saya sedang mencoba ...
template <typename...> struct type_list{};
// To concatenate
template <typename... Ts, typename... Us>
constexpr auto operator|(type_list<Ts...>, type_list<Us...>) {
return type_list{Ts{}..., Us{}...};
}
template <typename T, typename... Ts, typename... Us>
constexpr auto cross_product_two(type_list<T, Ts...>, type_list<Us...>) {
return (type_list<type_list<T,Us>...>{} | ... | type_list<type_list<Ts, Us>...>{});
}
template <typename T, typename U, typename... Ts>
constexpr auto cross_product_impl() {
if constexpr(sizeof...(Ts) >0) {
return cross_product_impl<decltype(cross_product_two(T{}, U{})), Ts...>();
} else {
return cross_product_two(T{}, U{});
}
}
Saya hanya akan mengatakan bahwa mengingat betapa sulitnya untuk melakukannya dengan benar, gunakan saja dorongan seperti dalam jawaban oleh Barry. Sayangnya saya harus terjebak dengan pendekatan linting tangan karena menggunakan boost atau tidak adalah keputusan yang berasal dari tempat lain :(
c++
templates
c++17
variadic-templates
themagicalyang
sumber
sumber
cartesian_product
adalah daftar daftar tipe, dan pada setiap langkah rekursi Anda ingin menambahkan item ke setiap daftar tipe dalam. Masuk ke tingkat pengemasan kedua dari paket ini membutuhkan pengurangan ...Jawaban:
Dengan Boost.Mp11 , ini adalah one-liner pendek (seperti biasa):
Demo .
sumber
algorithm.hpp
semua MP11. Dan bahkan kemudian kita berbicara 0,08 vs 0,12. Harus memperhitungkan berapa lama aku menulis ini juga.OK mengerti. Itu tidak cantik tapi berhasil:
https://godbolt.org/z/L5eamT
Saya meninggalkan
static_assert
tes saya sendiri di sana untuk ... Yah, saya harap mereka membantu.Juga, saya yakin harus ada solusi yang lebih baik. Tapi ini adalah jalan "Aku tahu ini pada akhirnya akan mengarah ke tujuan". Saya akhirnya harus menggunakan menambahkan
concat
atau macam-macam, saya yakin itu bisa digunakan lebih awal untuk melewati sebagian besar cruft.sumber
...
harus masuk ke dalam recursiveconcat
panggilan, bukan di luar. Jawaban (termasuk kasus uji) dikoreksi. Buktikan Barry benar tentang ekspektasi kebenaran :)cartesian_product
mengimplementasikan rekursi.multiply_all
melakukanmultiply_one
untuk setiap daftar tipe dalamTLs
paket.cartesian_product::type
adalah daftar daftar jenis.multiply_all
mengambil daftar jenis dan daftar daftar jenis.multiply_one
Dibutuhkan dua daftar jenisa1, a2, a3
danb1, b2, b3
dan menciptakana1, b1, b2, b3
,a2, b1, b2, b3
,a3, b1, b2, b3
. Anda memerlukan dua level deduksi (multiply_all
,multiply_one
) ini karena Anda harus menurunkan dua level "variadicness", lihat komentar pertama saya pada pertanyaan.Lipat ekspresi untuk menyelamatkan lagi
Dan kamu sudah selesai. Ini memiliki manfaat tambahan atas rekursi memiliki kedalaman instantiasi O (1).
sumber
using result = product_t<t1,t2,t3>
... beberapa cara untuk menggambarkannya sebagaiusing result = decltype(t1{} * t2{} * t3{});
. Hmm, nah sekarang sudah dipikir-pikir, karenadecltype
tidak bisa dihindari, cukup menggunakan alias yang Anda berikan lebih intuitif.