2010-08-08 68 views
19

tôi ghi lại một số mã trong đó sử dụng meta-lập trình nặng nề, ví dụ:C++ meta-lập trình doxygen tài liệu

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> { 

một cách tốt để ghi lại cấu trúc như vậy sử dụng doxygen là gì?

+0

Tôi nghĩ bạn cần viết tài liệu thích hợp, sử dụng trình xử lý văn bản. Nếu tôi bắt gặp các tài liệu doxy tạo thông thường (cho dù bạn có thêm chú thích thêm bao nhiêu) cho những thứ như thế này, tôi nghĩ tôi có lẽ sẽ nói "không cảm ơn". Nhưng sau đó tôi có lẽ sẽ nói nó anyway :-) –

+1

Đây chính xác là lý do tại sao tôi tránh xa template metaprogramming trong C++. Thật lố bịch. – You

+9

@Bạn không có cách nào tốt hơn để làm điều đó, không phải bằng bất kỳ ngôn ngữ nào – Anycorn

Trả lời

8

Sử dụng macro tiền xử lý. Dưới đây là một ví dụ từ the not-yet-official Boost.XInt library (hiện xếp hàng để xem xét để đưa vào Boost):

#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 

Sử dụng #define tên macro d thay vì các thông số mẫu, ở khắp mọi nơi bạn cần đến chúng, như vậy:

/*! \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 

Và đặt những dòng như thế này trong 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 

Kết quả là Doxygen thấy "..." hoặc "khác" cho thông số mẫu và trình biên dịch nhìn thấy những cái thực. Nếu bạn mô tả các tham số mẫu trong tài liệu cho chính lớp đó thì người dùng thư viện sẽ chỉ cần thấy chúng ở một nơi mà anh ấy có khả năng tìm kiếm chúng; chúng sẽ bị ẩn ở mọi nơi khác. Là một lợi thế bổ sung cho thiết kế này, nếu bạn cần thay đổi các danh sách tham số mẫu, bạn chỉ cần thay đổi chúng trong các định nghĩa macro và các hàm thực sự sử dụng các tham số đã thay đổi. Mọi thứ khác sẽ tự động điều chỉnh.

+2

Tôi ghét thêm các macro/mã bổ sung chỉ cho doxygen, như thể viết các chú thích tài liệu sẽ không đủ. Hy vọng họ sẽ sớm hỗ trợ các mẫu. –

+0

Đối với mã thư viện, sự tiện lợi của việc có tất cả tài liệu ở đầu ngón tay của người dùng theo cách được định dạng độc đáo vượt quá sự bất tiện cá nhân của tôi về việc phải thêm các macro và mã. YMMV. :-) –

0

Siêu lập trình dường như thực hiện các phép toán. Tôi sẽ viết các công thức toán học mô tả với thoát latex trong tài liệu doxygen.

+0

hi. Tôi có thể không làm cho mình rõ ràng, tôi cần phải lập trình logic tài liệu, chứ không phải là mô tả toán học. – Anycorn

+1

@aaa Tôi muốn nói rằng bạn cần phải ghi lại cả hai. –

+0

@aaa Logic lập trình nào vẫn còn trong đoạn được hiển thị khi bạn loại bỏ nó về C++ và kỹ thuật lập trình meta? –

3

Đây là quan điểm của tôi về nó:

/// 
/// \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> {}; 

/// \} 

Đừng quên để thêm gái giang hồ trong phần xác định trước của tiền xử lý Doxygen của.

Tôi thường thích ẩn chi tiết triển khai từ người dùng mã của mình, vì vậy tôi thay đổi những gì Doxygen thấy. Trong trường hợp này, bạn sẽ tìm thấy tất cả các chuyên môn của bạn trong một nhóm, nhóm Kernel và dưới danh sách lớp, tất cả các chuyên môn sẽ được nhóm lại với nhau và sẽ không có tên rất dài và không thể hiểu được.

Hy vọng điều đó sẽ hữu ích.

1

Tôi không thích giải pháp có macro/mã bổ sung, như the swine.

Đây là giải pháp của tôi dựa trên việc xử lý sau các trang HTML do Doxygen tạo.

Đây là tập lệnh python hoạt động trong Linux. Nó ngăn chặn tất cả các "< ...>" trong các trang Mẫu tham khảo và Cấu trúc, cũng như trong "Danh sách tất cả các trang thành viên" của chúng.

Ít và ít xâm lấn "mẫu < ...>" trước khi mỗi phương pháp được ghi lại vẫn còn.

Chạy tập lệnh bằng thư mục "html /" (nơi tài liệu được tạo) làm đối số.

#!/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) 
Các vấn đề liên quan