Şablon meta programlama


38

Birisi bana açıklayabilir, ilk şablon meta-programlama yolu neden sonsuz döngüye gidiyor, ikincisi doğru çalışıyor.

#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;
}


2
Amaç şablon meta programlamayı kullanmaktı. constexprbir seçenek değil.
Exxul

constexprBir seçenek olmadığını açıkça belirtmek için c ++ 98 etiketi eklendi . (C ++ 11'de tanıtıldı). Bu mevcut cevapları geçersiz kılar. Exxul, lütfen hangi C ++ sürümüyle sınırlı olduğunuzu açıklığa kavuşturun.
MSalters

Maalesef etiketi kaldırdım.
Exxul

Yanıtlar:


44
(N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val

Bu çizgi, her ikisinin de somutlaşmasına neden olur commondivs<N,(M-N)>::valve commondivs<(N-M),M>::valdurum derleme zamanında biliniyor olsa ve dallardan biri asla alınmaz.

Değiştir ? :ile std::conditional_tbu sınırlama yoktur ki,:

static const int val = std::conditional_t<N < M, commondivs<N,(M-N)>, commondivs<(N-M),M>>::val;

15

Sorun koşullu operatörün tüm işlenenler, değerlendirilen her iki yüzden edilecek olan commondivs<N,(M-N)>ve commondivs<(N-M),M>örneği ve onların olsun valsonra özyinelemeli şablon örneklerinin oluşturulmasına yol olsun değerlendirildi ve.

Eğer constexpr öğesini uygulayabilir ve constexpr staticüye işlevine koyabilirsiniz .

Değer ise true, ifade-false atılır (varsa), aksi takdirde, ifade-true atılır.

template<int N, int M>
struct commondivs {                                              
  constexpr static int get_val() {
    if constexpr (N<M) return commondivs<N,(M-N)>::val; // if true, the else part won't be evaluated
    else return commondivs<(N-M),M>::val;               // vice versa
  }
  static const int val = get_val();
};

CANLI


Değerlendirildi mi yoksa yeni mi başladı?
Daniel McLaury

@DanielMcLaury Değerlendirildi; sadece örneklenmiş değil.
songyuanyao

Her ::valiki dalda değerinin mutlaka üretilmesi gerekir, ancak bu yine de somutlaştırılır (statik sabit üyeli bir şablon). Çalışma zamanında Değerlendirilmesi yok değil de ... ne, belli ki ... derler asla değil çünkü can
Yararsız

8

Üçlü operatör şu şekilde değildir if constexpr: bir derleyici onu gördüğünde, her iki dal için kod üretmesi gerekir. Başka bir deyişle, bir şablon örneğini commondivs<M, N>, bir derleyici başlatır hem şablonlar commondivs<N, M - N>ve commondivs<N - M, M>.

Bunun aksine commondiv(N, M - N)ve commondiv(N - M, M)iki işlev çağrısına çevrilir. Hangisi alınır, fonksiyon gerçekten çağrıldığında karar verilir.

İlave.

HolyBlackCat ile bir çözüm verdi std::conditional_t. Işte başka biri:

template<int N, int M>
struct commondivs {                                              
    static constexpr int min = (N < M) ? N : M;
    static constexpr int max = (N < M) ? M : N;
    static constexpr int val = commondivs<min, max - min>::val;
};

template<int N>
struct commondivs<N, N> {
    static constexpr int val = N;
};

0

Sonsuz özyineleme elde edersiniz çünkü:

static const int val = (N<M) ? commondivs<N,(M-N)>::val : commondivs<(N-M),M>::val;

metatemplate programlama değildir ?:, çünkü @Eng'in dediği gibi değildir constexpr.

@ HolyBlackCat'ın cevabına bakmak istiyorsunuz.


1
Yardımcı olmaz. ?:değil constexpr.
Evg

Hayır deniyorum. Aynı sonsuz döngü.
Exxul
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.