Implementasi C++14 make_integer_sequence
Saya mencoba untuk menerapkan C++14 alias template make_integer_sequence
, yang menyederhanakan penciptaan kelas template integer_sequence
.
template< class T, T... I> struct integer_sequence
{
typedef T value_type;
static constexpr size_t size() noexcept { return sizeof...(I) ; }
};
template< class T, T N>
using make_integer_sequence = integer_sequence< T, 0,1,2, ... ,N-1 >; // only for illustration.
Untuk melaksanakan make_integer_sequence
kita butuh penolong struktur make_helper
.
template< class T , class N >
using make_integer_sequence = typename make_helper<T,N>::type;
Menerapkan make_helper
isn't terlalu sulit.
template< class T, T N, T... I >
struct make_helper
{
typedef typename mpl::if_< T(0) == N,
mpl::identity< integer_sequence<T,I...> >,
make_helper< T, N-1, N-1,I...>
>::type;
};
Untuk menguji make_integer_sequence
saya membuat ini fungsi utama:
int main()
{
#define GEN(z,n,temp) \
typedef make_integer_sequence< int, n > BOOST_PP_CAT(int_seq,n) ;
BOOST_PP_REPEAT(256, GEN, ~);
}
Aku menyusun program dengan GCC 4.8.0, quad-core i5 dengan sistem 8GBs RAM. Kompilasi sukses mengambil 4 detik.
Tapi, ketika saya mengubah GEN makro untuk:
int main() {
#define GEN(z,n,temp) \
typedef make_integer_sequence< int, n * 4 > BOOST_PP_CAT(int_seq, n) ;
BOOST_PP_REPEAT(256, GEN, ~ );
}
Kompilasi tidak berhasil dan ditampilkan pesan kesalahan:
virtual memori habis.
Bisakah seseorang menjelaskan kesalahan ini dan apa yang menyebabkannya?
EDIT:
Aku disederhanakan tes ke:
int main()
{
typedef make_integer_sequence< int, 4096 > int_seq4096;
}
Saya kemudian berhasil dikompilasi dengan GCC 4.8.0 -ftemplate-kedalaman=65536.
Namun yang kedua ini test:
int main()
{
typedef make_integer_sequence< int, 16384 > int_seq16384;
}
Tidak di compile dengan GCC 4.8.0 -ftemplate-kedalaman=65536, dan mengakibatkan kesalahan:
virtual memori habis.
Jadi, pertanyaan saya adalah, bagaimana cara menurunkan template dalam instansiasi?
Salam, Khurshid.
Berikut ini's
log N
implementasi yang doesn't bahkan perlu peningkatan max mendalam untuk template instantiasi dan mengkompilasi cukup cepat:Ini pada dasarnya adalah saya hacking sekitar Xeo's solusi: Membuat komunitas wiki - jika apresiatif, mohon upvote Xeo.
...hanya dimodifikasi sampai aku merasa itu tidak't mendapatkan lebih sederhana, berganti nama dan menambahkan
value_type
dansize()
per Standar (tapi hanya melakukanindex_sequence
tidakinteger_sequence
), dan kode bekerja dengan GCC 5.2-std=c++14
bisa berjalan jika tidak berubah di bawah lebih tua/lain-lain penyusun I'm terjebak dengan. Mungkin menyelamatkan seseorang beberapa waktu / kebingungan.Catatan:
"sihir" dari Xeo's solusi dalam deklarasi
_merge_and_renumber
(concat
di kode nya) dengan tepat dua parameter, sedangkan specilisation efektif menghadapkan mereka masing-masing parameter paketthe
typename
...::tipe
di...struct make_index_sequence : _merge_and_renumber<typename make_index_sequence<N/2>::jenis, typename make_index_sequence<N - N/2>::jenis>
menghindari kesalahan:
Saya menemukan sangat cepat dan tak jauh rekursi versi dari pelaksanaan
make_index_sequence
. Di PC saya mengkompilasi dengan N = 1 048 576 , dengan 2 s. (PC : Centos 6.4 x86, i5, 8 Gb RAM, gcc-4.4.7 -std=c++0x -O2 -Wall).Anda kehilangan
-1
di sini:secara khusus:
Selanjutnya, cabang pertama seharusnya't
integer_sequence<T>
, melainkaninteger_sequence<T, aku...>
.yang harus cukup untuk mendapatkan anda asli kode untuk mengkompilasi.
Secara umum, ketika menulis serius
template
metaprogramming, tujuan utama anda harus menjaga kedalamantemplate
instansiasi turun. Cara untuk berpikir tentang masalah ini adalah membayangkan anda memiliki pilihan yang tak terbatas-benang komputer: setiap perhitungan independen harus dikocok lepas ke thread sendiri, kemudian dikocok bersama-sama di akhir. Anda memiliki beberapa operasi yang mengambil O(1) kedalaman, seperti...
ekspansi: mengeksploitasi mereka.Biasanya, menarik logaritma kedalaman yang cukup, karena dengan
900
mendalam, yang memungkinkan2^900
berukuran struktur, dan sesuatu yang lain istirahat pertama. (Untuk menjadi adil, apa yang lebih mungkin terjadi adalah 90 lapisan yang berbeda dari2^10
berukuran struktur).Berikut ini adalah sedikit lebih umum variasi Xeo's logaritma jawaban yang menyediakan
make_integer_sequence
untuk sewenang-wenang jenis. Hal ini dilakukan dengan menggunakanstd::integral_constant
dalam rangka untuk menghindari ditakuti "argumen template yang melibatkan parameter template" kesalahan.Demo: coliru
Implementasi sederhana O(N). Mungkin bukan apa yang anda inginkan untuk besar N, tapi saya aplikasi ini hanya untuk memanggil fungsi dengan diindeks argumen, dan saya tidak't mengharapkan tual membaca, keakraban lebih dari sekitar 10. Aku ingin't diisi anggota integer_sequence. I'm looking forward untuk menggunakan library standar pelaksanaan dan nuking ini :)