टेम्प्लेट मेटा प्रोग्रामिंग


38

क्या कोई मुझे समझा सकता है, कि पहला टेम्प्लेट मेटा-प्रोग्रामिंग तरीका अनंत लूप में क्यों जा रहा है, लेकिन दूसरा सही ढंग से चलता है।

#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
लक्ष्य टेम्पलेट मेटा प्रोग्रामिंग का उपयोग करना था। constexprएक विकल्प नहीं है।
एक्सएक्सएक्स

जोड़ा गया c ++ 98 टैग स्पष्ट करने के लिए कि constexprएक विकल्प नहीं है। (इसे C ++ 11 में पेश किया गया था)। यह मौजूदा उत्तरों को अमान्य करता है। Exxul, कृपया स्पष्ट करें कि आप किस C ++ संस्करण तक सीमित हैं।
MSalters

क्षमा करें मैंने टैग हटा दिया।
एक्सएक्सएक्स

जवाबों:


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

यह रेखा दोनों के तात्कालिकता का कारण बनती है , commondivs<N,(M-N)>::valऔर commondivs<(N-M),M>::valभले ही स्थिति को संकलन समय पर जाना जाता है और शाखाओं में से एक को कभी नहीं लिया जाएगा।

इसके ? :साथ बदलें std::conditional_t, जिसमें यह सीमा नहीं है:

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

15

समस्या सभी सशर्त ऑपरेटर की ऑपरेंड, मूल्यांकन किया जाएगा दोनों बहुत है commondivs<N,(M-N)>और commondivs<(N-M),M>instantiated हो और उनके valget का मूल्यांकन किया और उसके बाद पुनरावर्ती टेम्पलेट इन्स्टेन्शियशन पर ले जाया जाता।

आप आवेदन कर सकते हैं , तो constexpr और एक में रख constexpr staticसदस्य कार्य करते हैं।

यदि मान है true, तो कथन-असत्य को छोड़ दिया जाता है (यदि वर्तमान में), अन्यथा, कथन-सत्य को छोड़ दिया जाता है।

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();
};

लाइव


मूल्यांकन किया गया या सिर्फ त्वरित किया गया?
डैनियल मैक्लॉरी

@DanielMcLaury मूल्यांकन; सिर्फ तात्कालिक नहीं।
गीतयुआनओ

मूल्य ::valको दोनों शाखाओं पर उत्पन्न किया जाना सुनिश्चित है, लेकिन यह अभी भी तात्कालिकता है (एक स्थिर कास्ट सदस्य के साथ एक टेम्पलेट)। रन टाइम पर मूल्यांकन नहीं होता ... ठीक है, यह स्पष्ट रूप से नहीं हो सकता है क्योंकि यह कभी नहीं संकलन ...
बेकार

8

टर्नेरी ऑपरेटर ऐसा नहीं है if constexpr: जब कोई कंपाइलर इसे देखता है, तो उसे दोनों शाखाओं के लिए कोड जनरेट करना पड़ता है। दूसरे शब्दों में, एक टेम्पलेट का दृष्टांत को commondivs<M, N>, एक संकलक को दर्शाता है दोनों टेम्पलेट्स commondivs<N, M - N>और commondivs<N - M, M>

इसके विपरीत, commondiv(N, M - N)और commondiv(N - M, M)दो फ़ंक्शन कॉल में अनुवादित हैं। कौन सा लिया जाता है, यह तय किया जाएगा कि फ़ंक्शन वास्तव में कहा जाता है।

इसके अलावा।

HolyBlackCat ने एक समाधान दिया std::conditional_t। यहाँ एक और एक है:

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

आपको अनंत पुनरावृत्ति मिलती है क्योंकि:

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

जैसा ?:कि @Eng कहते हैं, बिल्कुल भी मेटेटमप्लेट प्रोग्रामिंग नहीं है constexpr

आप @ HolyBlackCat के उत्तर को देखना चाहते हैं।


1
यह मदद नहीं करेगा। ?:नहीं है constexpr
Evg

नहीं, मैं कोशिश करता हूं। वही अनंत पाश।
एक्सएक्सएक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.