2010-08-08 18 views
19

मैं कुछ कोड जो काफी हद तक प्रोग्रामिंग मेटा, उदाहरण के लिए उपयोग करता दस्तावेजीकरण कर रहा हूँ:सी ++ मेटा प्रोग्रामिंग Doxygen प्रलेखन

template<rysq::type A, rysq::type B, rysq::type C, rysq::type D, class Transform> 
struct Kernel<meta::braket<A,B,C,D>, Transform, 
       typename boost::enable_if< 
        quadrature<meta::braket<A,B,C,D>, Transform> >::type> 
: Eri <Transform> { 

क्या Doxygen का उपयोग कर इस तरह के निर्माण दस्तावेज़ के लिए एक अच्छा तरीका है?

+0

मुझे लगता है कि आपको एक शब्द-प्रोसेसर का उपयोग करके उचित दस्तावेज लिखने की आवश्यकता है। यदि मैं इस तरह की चीजों के लिए सामान्य डॉक्स उत्पन्न दस्तावेज़ों (चाहे आप कितनी अतिरिक्त एनोटेशन जोड़ते हैं) में आए, मुझे लगता है कि मैं शायद "धन्यवाद नहीं" कहूंगा। लेकिन फिर मैं शायद इसे वैसे भी कहूंगा :-) –

+1

यही कारण है कि मैं सी ++ में टेम्पलेट मेटाप्रोग्रामिंग से दूर रहता हूं। यह हास्यास्पद है। – You

+9

@ आप इसे करने के लिए एक बेहतर तरीका नहीं है, किसी भी भाषा में नहीं – Anycorn

उत्तर

8

प्रीप्रोसेसर मैक्रोज़ का उपयोग करें।

#ifdef BOOST_XINT_DOXYGEN_IGNORE 
    // The documentation should see a simplified version of the template 
    // parameters. 
    #define BOOST_XINT_INITIAL_APARAMS ... 
    #define BOOST_XINT_CLASS_APARAMS ... 
    #define BOOST_XINT_CLASS_BPARAMS other 
    #define BOOST_XINT_APARAMS ... 
    #define BOOST_XINT_BPARAMS other 
#else 
    #define BOOST_XINT_INITIAL_APARAMS \ 
     class A0 = parameter::void_, \ 
     class A1 = parameter::void_, \ 
     class A2 = parameter::void_, \ 
     class A3 = parameter::void_, \ 
     class A4 = parameter::void_, \ 
     class A5 = parameter::void_ 
    #define BOOST_XINT_CLASS_APARAMS class A0, class A1, class A2, class A3, \ 
     class A4, class A5 
    #define BOOST_XINT_APARAMS A0, A1, A2, A3, A4, A5 
    #define BOOST_XINT_CLASS_BPARAMS class B0, class B1, class B2, class B3, \ 
     class B4, class B5 
    #define BOOST_XINT_BPARAMS B0, B1, B2, B3, B4, B5 
#endif 

टेम्पलेट मापदंडों के बजाय #define घ मैक्रो नाम का उपयोग करें, हर जगह आप उन्हें जरूरत है ताकि तरह:: यहाँ the not-yet-official Boost.XInt library से एक उदाहरण (वर्तमान में बूस्ट में शामिल करने के लिए समीक्षा के लिए पंक्तिबद्ध) है

/*! \brief The integer_t class template. 

This class implements the standard aribitrary-length %integer type. 

[...lots more documentation omitted...] 
*/ 
template<BOOST_XINT_INITIAL_APARAMS> 
class integer_t: virtual public detail::integer_t_data<BOOST_XINT_APARAMS>, 
    public detail::nan_functions<detail::integer_t_data<BOOST_XINT_APARAMS>:: 
    NothrowType::value, // ...lots more base classes omitted... 
{ 
    // ...etcetera 

और Doxyfile में इस तरह की लाइनें डाल:

PREDEFINED    = BOOST_XINT_DOXYGEN_IGNORE 

EXPAND_AS_DEFINED  = BOOST_XINT_INITIAL_APARAMS \ 
         BOOST_XINT_CLASS_APARAMS \ 
         BOOST_XINT_CLASS_BPARAMS \ 
         BOOST_XINT_APARAMS \ 
         BOOST_XINT_BPARAMS 

नतीजा यह है कि Doxygen देखता है या तो "..." या टेम्पलेट मापदंडों के लिए "अन्य", और संकलक वास्तविक लोगों को देखता है। यदि आप कक्षा के लिए दस्तावेज़ में टेम्पलेट पैरामीटर का वर्णन करते हैं, तो लाइब्रेरी के उपयोगकर्ता को केवल उन्हें उस स्थान पर देखने की आवश्यकता होगी, जिसे वह ढूंढने की संभावना है; वे हर जगह छिपाए जाएंगे।

इस डिज़ाइन के लिए अतिरिक्त लाभ के रूप में, यदि आपको कभी भी टेम्पलेट पैरामीटर सूचियों में परिवर्तन करने की आवश्यकता है, तो आपको केवल उन्हें मैक्रो परिभाषाओं और उन कार्यों को बदलने की आवश्यकता है जो वास्तव में परिवर्तित पैरामीटर का उपयोग करते हैं। बाकी सब कुछ स्वचालित रूप से अनुकूलित हो जाएगा।

/// 
/// \defgroup Kernel Kernel 
/// 
/// \brief Kernel does this and that 
/// \{ 

/// \brief Kernel template class brief description. 
template<Braket,Transform,Boolean> 
struct Kernel 
{}; 

/// \brief Kernel partial template specialization brief description. 
/// 
/// More detailed description...<br> 
/// Partially specializes Kernel with meta::braket<A,B,C,D\>.<br> 
/// If quadrature<meta::braket<A,B,C,D\>, Transform\> is true then enable 
/// this algorithm, otherwise enable this other algorithm.<br> 
/// Inherits privately from template class Eri<Transform\><br> 
/// \tparam A   template parameter A of type rysq::type, documentation and concepts 
/// \tparam B   template parameter B of type rysq::type, documentation and concepts 
/// \tparam C   template parameter C of type rysq::type, documentation and concepts 
/// \tparam D   template parameter D of type rysq::type, documentation and concepts 
/// \tparam Transform template parameter class Transform documentation and concepts 
/// \see Kernel\<Braket,Transform,Boolean\> 
/// \see Eri 
/// \see meta::braket 
/// \see quadrature 
#ifdef DOXY 
// This is the documentation version 
template<A,B,C,D,Transform> 
struct Kernel<Braket,Transform,Boolean> 
#else 
// This is what gets compiled 
template<rysq::type A, rysq::type B, rysq::type C, rysq::type D, class Transform> 
struct Kernel<meta::braket<A,B,C,D>, Transform,typename boost::enable_if<quadrature<meta::braket<A,B,C,D>, Transform> >::type> 
#endif 
: Eri <Transform> {}; 

/// \} 

Doxygen के पूर्वप्रक्रमक के पूर्वनिर्धारित खंड में डॉक्सी जोड़ने के लिए मत भूलना:

+2

मुझे डॉक्सिजन के लिए अतिरिक्त मैक्रोज़/कोड जोड़ने से नफरत है, जैसे कि दस्तावेज़ीकरण टिप्पणियां लिखना पर्याप्त नहीं होगा। उम्मीद है कि वे जल्द ही टेम्पलेट का समर्थन करेंगे। –

+0

लाइब्रेरी कोड के लिए, उपयोगकर्ता की उंगलियों पर सभी दस्तावेज रखने की सुविधा अच्छी तरह से स्वरूपित तरीके से मैक्रोज़ और कोड जोड़ने की मेरी व्यक्तिगत असुविधा से अधिक है। YMMV। :-) –

0

मेटा-प्रोग्रामिंग गणित को लागू करने लगता है। मैं डॉक्सिजन दस्तावेज में लेटेक्स से बचने के साथ वर्णित गणितीय सूत्रों को लिखूंगा।

+0

हाय। मैं खुद को स्पष्ट नहीं कर सकता, मुझे गणितीय विवरण की बजाय प्रोग्रामिंग तर्क दस्तावेज करने की आवश्यकता है। – Anycorn

+1

@aaa मैं कहूंगा कि आपको दोनों को दस्तावेज करने की आवश्यकता है। –

+0

@aaa जब आप इसे C++ और मेटा-प्रोग्रामिंग तकनीशियनों को स्ट्रिप करते हैं तो प्रोग्रामिंग तर्क दिखाया गया खंड में क्या रहता है? –

3

यहाँ उस पर मेरी ले है।

मैं आमतौर पर अपने कोड के उपयोगकर्ता से कार्यान्वयन विवरण छिपाना पसंद करता हूं, इसलिए मैं डॉक्सिजन को देखता हूं। इस मामले में, आपको एक समूह, कर्नेल समूह और कक्षा सूची के तहत आपकी सभी विशेषज्ञताएं मिलेंगी, सभी विशेषज्ञताओं को एक साथ समूहीकृत किया जाएगा और उनके पास बहुत लंबा और अनजान नाम नहीं होगा।

उम्मीद है कि यह मदद करता है।

1

मुझे अतिरिक्त मैक्रोज़/कोड के साथ समाधान पसंद नहीं है, जैसे the swine

डॉक्सिजन द्वारा जेनरेट किए गए HTML पृष्ठों की पोस्ट-प्रोसेसिंग के आधार पर मेरा समाधान यहां दिया गया है।

यह एक पायथन लिपि है जो लिनक्स के तहत काम करता है। यह टेम्पलेट क्लासेस और स्ट्रक्चर रेफरेंस पेजों में और "सभी सदस्यों के पृष्ठों की सूची" में सभी "< ...>" को दबा देता है।

छोटे और कम आक्रामक "टेम्पलेट < ...>" प्रत्येक दस्तावेज़ विधि से पहले बनी हुई है।

तर्क के रूप में "html /" निर्देशिका (जहां प्रलेखन उत्पन्न हुआ था) के साथ स्क्रिप्ट चलाएं।

#!/usr/bin/python 

import subprocess 
import sys 
import re 

def processFile(fileName): 

    f = open(fileName, 'r') 

    content = f.read(); 

    f.close(); 

    regex = re.compile("(&lt;.*&gt;).*(Template Reference|Member List)") 

    match = re.search(regex, content) 

    if not match: 
    return 

    toRemove = match.group(1) 

    regex = re.compile(toRemove) 

    content = re.sub(regex, "", content) 

    f = open(fileName, 'w') 

    f.write(content) 

    f.close() 


path = sys.argv[1] 

finder = subprocess.Popen(["find", path, "-name", "class*.html", "-o", "-name", "struct*.html"], stdout = subprocess.PIPE) 

(files, junk) = finder.communicate() 

files = files.splitlines() 

print files 

for fname in files: 
    if fname == "": 
continue 
    processFile(fname) 
संबंधित मुद्दे