Dapatkah seseorang menjelaskan kepada saya, mengapa cara meta-pemrograman templat pertama akan infinite loop, tetapi yang kedua berjalan dengan benar.
#include <iostream>
using namespace std;
template<int N, int M>
struct commondivs {
static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val;
};
template<int N>
struct commondivs<N,N> {
static const int val = N;
};
int commondiv(int N, int M){
if(N==M){
return N;
}
return (N<M)?commondiv(N,(M-N)):commondiv((N-M),M);
}
int main() {
cout << commondivs<9,6>::val << endl;
cout << commondiv(9,6) << endl;
return 0;
}
constexpr
bukan pilihan.constexpr
bukan pilihan. (Ini diperkenalkan di C ++ 11). Itu tidak valid jawaban yang ada. Exxul, tolong jelaskan versi C ++ mana yang Anda terbatas.Jawaban:
Baris ini menyebabkan instantiasi keduanya
commondivs<N,(M-N)>::val
dancommondivs<(N-M),M>::val
, bahkan jika kondisi diketahui pada waktu kompilasi dan salah satu cabang tidak akan pernah diambil.Ganti
? :
denganstd::conditional_t
, yang tidak memiliki batasan ini:sumber
Masalahnya adalah semua operan dari operator kondisional akan dievaluasi, sehingga keduanya
commondivs<N,(M-N)>
dancommondivs<(N-M),M>
akan dipakai dan merekaval
dievaluasi dan kemudian mengarah ke instantiasi templat rekursif.Anda dapat menerapkan constexpr jika dan memasukkannya ke dalam
constexpr
static
fungsi anggota.HIDUP
sumber
::val
harus dihasilkan di kedua cabang yakin, tetapi ini masih instantiation (dari template dengan anggota const statis). Evaluasi pada waktu berjalan tidak terjadi ... yah, jelas tidak bisa karena tidak pernah dikompilasi ...Operator ternary tidak seperti
if constexpr
: ketika kompilator melihatnya, ia harus membuat kode untuk kedua cabang. Dengan kata lain, untuk instantiate templatecommondivs<M, N>
, kompiler instantiates baik templatecommondivs<N, M - N>
dancommondivs<N - M, M>
.Berbeda dengan itu,
commondiv(N, M - N)
dancommondiv(N - M, M)
diterjemahkan ke dalam dua panggilan fungsi. Yang mana yang diambil, akan diputuskan ketika fungsi tersebut benar-benar dipanggil.Tambahan.
HolyBlackCat memberikan solusi
std::conditional_t
. Ini satu lagi:sumber
Anda mendapatkan rekursi tak terbatas karena:
sama sekali bukan pemrograman metatemplate karena
?:
, seperti yang dikatakan @Eng, tidakconstexpr
.Anda ingin melihat jawaban @ HolyBlackCat.
sumber
?:
tidakconstexpr
.