2009-08-02 40 views
25

Tôi muốn gỡ lỗi một số mã templated để hiểu nó tốt hơn.
Đáng tiếc là tôi mới vào mẫu Lập trình meta và thật khó cho tôi để nhận được trongC++ Mẫu Lập trình meta - Có thể xuất mã được tạo ra không?

Khi tôi cố gắng ra các tập tin nguồn preprocessed tôi nhận được 125 000 dòng mã:./

Vậy là có một cách tôi có thể nhìn thấy mã được tạo ra? (Thư viện tôi đang sử dụng là SeqAn)

+2

Không, nhưng nó phải là. Ai đó nên làm điều này như một dự án Clang: D –

+0

Lưu ý rằng do [SFINAE] (https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error) mã bạn muốn có được bằng cách thay thế từng mẫu bằng một số thay thế được mã hóa cứng có thể sẽ là bất hợp pháp. Ví dụ. miễn là nó không bao giờ được gọi, một phương thức của một lớp mẫu cũng có thể gọi những thứ không tồn tại. – MvG

+1

@JosephGarvin Có một dự án dựa trên Clang (s) cho việc này ngay bây giờ. Phiên bản hoạt động mới nhất của [Templight, trình chỉnh sửa và trình gỡ lỗi mẫu dựa trên clang-based] (https://github.com/mikael-s-persson/templight), [Trình hiển thị Templar] (https://github.com/ schulmar/Templar), cũng như [Metashell] (https://github.com/sabel83/metashell). –

Trả lời

21

Không. Bộ tiền xử lý không có gì liên quan đến việc xử lý mẫu, được trình biên dịch thực hiện. Các mẫu không tạo mã C++, bất kỳ một hàm nào khác ngoài một lời gọi hàm - chúng là một phần không tách rời của chính ngôn ngữ C++.

+0

Trong khi điều này nói chung là đúng, đó là trong lý thuyết cũng đúng cho preprocessor. Trong thực tế, việc thực hiện dễ nhất là tạo ra mã C++ giống như đầu ra của giai đoạn tiền xử lý, nhưng không phải là cho các sự kiện mẫu. Việc đảo ngược sẽ là vô cùng khó khăn nhưng không thể về mặt kỹ thuật. Vấn đề chính là tra cứu tên, và trình biên dịch có thể tạo ra các tên duy nhất trong quá trình tạo mẫu. – MSalters

+0

Thành thật mà nói, bạn vẫn có thể sử dụng trình gỡ lỗi để hiển thị loại được tính nếu bạn khởi tạo nó. Tôi đã làm một ví dụ làm thế nào để sử dụng Visual C++. Tôi thường sử dụng nó cho các chương trình meta của mình. – ovanes

5

Đây là khả năng câu trả lời cho câu hỏi của bạn:

C++ Template preprocessor tool

Dường như đã thỏa mãn người cuối cùng người hỏi - mặc dù tôi không thể tưởng tượng tại sao! Đầu ra của trình biên dịch C++ trong C thường khá dễ đọc, vì nó không có ý định trợ giúp để hiểu, chỉ đơn thuần là một loại ngôn ngữ lắp ráp di động.

1

nói chung không thể xuất toàn bộ mã. Nhưng những gì tôi thấy cực kỳ thú vị, là khả năng sử dụng trình gỡ lỗi Visual C++ để hiển thị cho bạn loại. Sử dụng chương trình meta đơn giản đó:

template<class Head, class Tail> 
struct type_list 
{ 
    typedef Head head; 
    typedef Tail tail; 
}; 

struct null_type 
{}; 

template<class List> 
struct list_head 
{ 
    typedef typename List::head head; 
}; 

template<class List> 
struct list_tail 
{ 
    typedef typename List::tail tail; 
}; 

template<class List> 
struct list_length 
{ 
    static const size_t length = 1+list_length< typename list_tail<List>::tail >::length; 
}; 

template<> 
struct list_length<null_type> 
{ 
    static const size_t length = 0; 
}; 


int main() 
{ 
    typedef 
    type_list 
    < int 
    , type_list 
     < double 
     , type_list 
     < char 
     , null_type 
     > 
     > 
    >  my_types; 

    my_types test1; 

    size_t length=list_length<my_types>::length; 

    list_head<list_tail<list_tail<my_types>::tail>::tail>::head test2; 

} 

Tôi vừa khởi tạo các loại meta của mình. Đây vẫn là các cá thể lớp C++ rỗng, dài ít nhất 1 byte. Bây giờ tôi có thể đặt một breakpoint sau khi instantiation cuối cùng của test2 xem, mà loại/giá trị chiều dài, test1 và test2 là của:

Dưới đây là những gì các chương trình gỡ rối cho thấy:

length 3 unsigned int 
test1 {...} type_list<int,type_list<double,type_list<char,null_type> > > 
test2 -52 'Ì' char 

Bây giờ bạn bạn biết đầu trả về cho bạn một ký tự, danh sách của bạn chứa int, double, char và được kết thúc bằng null_type.

Điều đó đã giúp tôi rất nhiều. Đôi khi bạn cần phải sao chép các loại thực sự lộn xộn đến một trình soạn thảo văn bản và định dạng nó thành một dạng có thể đọc được, nhưng điều đó mang đến cho bạn khả năng để theo dõi những gì bên trong và cách nó được tính toán.

Hy vọng rằng sẽ giúp,
Ovanes

22

Nope, nói chung, nó có thể không được thực hiện. Các khuôn mẫu đơn giản là một phần của ngôn ngữ C++, chúng không phải là một bộ tiền xử lý riêng biệt, do đó chúng không tạo ra mã C++.

Giải pháp thông thường là rắc mã của bạn bằng các xác nhận tĩnh và các kiểm tra khác để xác minh rằng các mẫu bên phải được tạo theo đúng cách.

Một khi bạn bắt đầu đi lạc trong lập trình meta của bạn, thủ thuật đơn giản này có thể giúp bạn xác định loại một số mẫu thực sự là:

// given a variable t of an unknown type T 
int*** i = t; 

Khi trình biên dịch gặp này, nó sẽ in ra một tốt đẹp và đơn giản thông báo lỗi "Không thể chuyển đổi <long, detailed typename> thành int ***", cho phép bạn dễ dàng xác minh rằng thông số mẫu T thực sự là loại bạn cho là đúng.

14

Kiểm tra my publication on C++ template metaprogram debugging

Từ trang 6 bạn có thể xem cách hoạt động. Đối với các mục đích cụ thể, bạn sẽ không cần toàn bộ chuỗi công cụ, nó có thể được thực hiện bằng tay.

Tôi đã đặt cùng một bổ trợ Visual C++, nơi bạn có thể đặt điểm ngắt vv nhưng đó là một bằng chứng về khái niệm hơn một công cụ để sử dụng hàng ngày.

Chúng tôi đã làm việc trên giao diện đồ họa hiển thị tất cả các cảnh báo, cho phép gỡ lỗi, lược tả. Rất tiếc, chúng tôi không thể hứa hẹn bất kỳ ngày xuất bản nào cho công cụ đó, vì chúng tôi làm điều đó trong thời gian miễn phí khá hạn chế của chúng tôi.

UPDATE: trình gỡ lỗi và profiler có sẵn here

UPDATE: C++Now presentation

+0

Có vẻ thú vị! –

Các vấn đề liên quan