Contoh
#include <iostream>
template <int N> struct Factorial
{
enum { val = Factorial<N-1>::val * N };
};
template<>
struct Factorial<0>
{
enum { val = 1 };
};
int main()
{
// Note this value is generated at compile time.
// Also note that most compilers have a limit on the depth of the recursion available.
std::cout << Factorial<4>::val << "\n";
}
Itu sedikit menyenangkan tapi tidak terlalu praktis.
Untuk menjawab bagian kedua dari pertanyaan:
Apakah fakta ini berguna dalam praktiknya?
Jawaban Singkat: Semacam.
Jawaban Panjang: Ya, tetapi hanya jika Anda adalah daemon template.
Untuk menghasilkan pemrograman yang bagus dengan menggunakan template meta-pemrograman yang benar-benar berguna untuk digunakan orang lain (yaitu perpustakaan) benar-benar sangat sulit (meskipun dapat dilakukan). Untuk Membantu meningkatkan bahkan memiliki MPL alias (Meta Programming Library). Tapi coba debugging kesalahan kompiler dalam kode template Anda dan Anda akan berada dalam perjalanan panjang yang sulit.
Tetapi contoh praktis yang baik tentang itu digunakan untuk sesuatu yang bermanfaat:
Scott Meyers telah bekerja ekstensi ke bahasa C ++ (saya menggunakan istilah longgar) menggunakan fasilitas template. Anda dapat membaca tentang pekerjaannya di sini ' Fitur Penegakan Kode '
Saya telah melakukan mesin turing di C ++ 11. Fitur yang ditambahkan C ++ 11 memang tidak signifikan untuk mesin turing. Ini hanya menyediakan untuk daftar aturan panjang sewenang-wenang menggunakan templat variadic, daripada menggunakan metaprogramming makro yang sesat :). Nama untuk kondisi digunakan untuk menampilkan diagram di stdout. Saya telah menghapus kode itu agar sampelnya tetap pendek.
sumber
" C ++ Templates Are Turing Complete " memberikan implementasi mesin Turing dalam template ... yang tidak sepele dan membuktikan maksudnya dengan cara yang sangat langsung. Tentu saja, ini juga tidak terlalu berguna!
sumber
C ++ saya agak berkarat, jadi mungkin tidak sempurna, tapi hampir saja.
Intinya adalah untuk menunjukkan bahwa kompilator mengevaluasi sepenuhnya definisi rekursif hingga mencapai jawaban.
sumber
Untuk memberikan contoh yang tidak sepele: http://gitorious.org/metatrace , C ++ compile time ray tracer.
Perhatikan bahwa C ++ 0x akan menambahkan fasilitas non-template, compile-time, turing-complete berupa
constexpr
:Anda dapat menggunakan
constexpr
-expression di mana pun Anda membutuhkan kompilasi konstanta waktu, tetapi Anda juga dapat memanggilconstexpr
-functions dengan parameter non-const.Satu hal yang keren adalah bahwa ini akhirnya akan memungkinkan waktu kompilasi matematika floating point, meskipun standar secara eksplisit menyatakan bahwa waktu kompilasi aritmatika floating point tidak harus cocok dengan runtime aritmatika floating point:
sumber
The Book Modern C ++ Design - Generic Programming and Design Pattern oleh Andrei Alexandrescu adalah tempat terbaik untuk mendapatkan pengalaman langsung dengan pola pemrograman umum yang berguna dan kuat.
sumber
Contoh faktorial sebenarnya tidak menunjukkan bahwa template sudah lengkap Turing, melainkan menunjukkan bahwa template tersebut mendukung Primitive Recursion. Cara termudah untuk menunjukkan bahwa templat sudah lengkap adalah dengan tesis Church-Turing, yaitu dengan mengimplementasikan mesin Turing (berantakan dan sedikit tidak berguna) atau tiga aturan (app, abs var) dari kalkulus lambda tanpa tipe. Yang terakhir jauh lebih sederhana dan jauh lebih menarik.
Apa yang didiskusikan adalah fitur yang sangat berguna ketika Anda memahami bahwa template C ++ memungkinkan pemrograman fungsional murni pada waktu kompilasi, formalisme yang ekspresif, kuat dan elegan tetapi juga sangat rumit untuk ditulis jika Anda memiliki sedikit pengalaman. Perhatikan juga berapa banyak orang yang menemukan bahwa mendapatkan kode yang sangat bertemplatasi sering kali memerlukan usaha yang besar: hal ini persis terjadi pada bahasa fungsional (murni), yang membuat kompilasi lebih sulit tetapi secara mengejutkan menghasilkan kode yang tidak memerlukan debugging.
sumber
Saya pikir itu disebut meta-programming template .
sumber
Nah, berikut ini adalah waktu kompilasi implementasi Turing Machine yang menjalankan berang-berang sibuk dengan 2 simbol 4-status
Uji coba Ideone: https://ideone.com/MvBU3Z
Penjelasan: http://victorkomarov.blogspot.ru/2016/03/compile-time-turing-machine.html
Github dengan lebih banyak contoh: https://github.com/fnz/CTTM
sumber
Anda dapat memeriksa artikel ini dari Dr. Dobbs tentang implementasi FFT dengan template yang menurut saya tidak sepele. Poin utamanya adalah memungkinkan kompiler untuk melakukan optimasi yang lebih baik daripada implementasi non template karena algoritma FFT menggunakan banyak konstanta (misalnya tabel sin)
bagian I
Bagian II
sumber
Ini juga menyenangkan untuk menunjukkan bahwa ini adalah bahasa yang berfungsi murni meskipun hampir tidak mungkin untuk di-debug. Jika Anda melihat posting James Anda akan melihat apa yang saya maksud dengan berfungsi. Secara umum, ini bukan fitur C ++ yang paling berguna. Itu tidak dirancang untuk melakukan ini. Itu adalah sesuatu yang ditemukan.
sumber
Mungkin berguna jika Anda ingin menghitung konstanta pada waktu kompilasi, setidaknya dalam teori. Lihat pemrograman metaprogram .
sumber
Contoh yang cukup berguna adalah kelas rasio. Ada beberapa varian yang beredar. Menangkap kasus D == 0 cukup sederhana dengan sebagian kelebihan beban. Komputasi sebenarnya adalah menghitung GCD dari N dan D dan waktu kompilasi. Ini penting saat Anda menggunakan rasio ini dalam penghitungan waktu kompilasi.
Contoh: Saat Anda menghitung sentimeter (5) * kilometer (5), pada waktu kompilasi Anda akan mengalikan rasio <1.100> dan rasio <1000,1>. Untuk mencegah overflow, Anda menginginkan rasio <10,1> daripada rasio <1000.100>.
sumber
Sebuah mesin Turing adalah Turing-lengkap, tapi itu tidak berarti Anda harus ingin menggunakan satu untuk kode produksi.
Mencoba melakukan sesuatu yang tidak sepele dengan templat menurut pengalaman saya berantakan, jelek, dan tidak berguna. Anda tidak memiliki cara untuk "men-debug" "kode" Anda, pesan kesalahan waktu kompilasi akan menjadi samar dan biasanya di tempat yang paling tidak mungkin, dan Anda dapat memperoleh manfaat kinerja yang sama dengan cara yang berbeda. (Petunjuk: 4! = 24). Lebih buruk lagi, kode Anda tidak dapat dipahami oleh programmer C ++ rata-rata, dan kemungkinan besar akan non-portabel karena tingkat dukungan yang luas dalam kompiler saat ini.
Template sangat bagus untuk pembuatan kode generik (kelas kontainer, pembungkus kelas, campuran), tetapi tidak - menurut saya Turing Completeness of templates TIDAK BERGUNA dalam praktiknya.
sumber
Contoh lain bagaimana tidak memprogram:
Posting di C ++ template sudah selesai
sumber
K17<Depth+1>::x * 5
.