2011-12-19 16 views
6

Tôi có chức năng ghi nhật ký được gọi tại một vài nơi trong suốt mã. Với mỗi nhật ký, tôi phải cung cấp 2 hằng số thời gian biên dịch. Có 2 phương pháp để thực hiện:Cách tiếp cận nào tốt hơn để cung cấp hằng số thời gian biên dịch cho một hàm? Đối số chức năng so với tham số mẫu

(1) Chức năng lập luận:

template<typename T> 
void log (const T &obj, const int LINE, const int COUNT) 
{ 
    // T is used for some purpose 
    if(debug) 
    logging(obj.out(), LINE, COUNT); 
} 

gọi nó như là,

log(str, __LINE__, __COUNTER__); 

(2) tham số Template:

template<typename T, int LINE, int COUNT> 
void log (T &obj) 
{ 
    // T is used for some purpose 
    if(debug) 
    logging(obj.out(), LINE, COUNT); 
} 

gọi là,

log<__LINE__, __COUNTER__>(str); 

Tôi không thể quyết định, bởi vì cách tiếp cận đầu tiên mang đến sự đơn giản, nhưng chúng tôi đang chuyển đổi liên tục tại thời gian biên dịch. Cách tiếp cận thứ 2 là hoàn hảo, nhưng thời gian biên dịch có lẽ sẽ tăng lên. Nhiệm vụ này tẻ nhạt, và tôi chưa thực hiện bất kỳ công việc nào trong số đó, vì vậy tôi không có bất kỳ nhãn hiệu băng ghế dự bị nào.

Sẽ là một trợ giúp tuyệt vời nếu ai đó có thể trả lời câu hỏi này từ trải nghiệm/kiến ​​thức của họ.

+1

Làm thế nào để bạn xác định "tốt hơn"? Cả hai đều làm việc *, vậy bạn sẽ sử dụng tiêu chuẩn nào để nói rằng cái nào tốt hơn cái kia? –

+0

@NicolBolas, vì tôi muốn chọn tốt hơn trong số 2 dựa trên thời gian biên soạn và thời gian chạy. Ngoài ra còn có một sửa đổi nhỏ trong mã ví dụ. – iammilind

+0

Bất kể hàm 'logging' nào, nó sẽ * chắc chắn nhất * chậm hơn so với truyền hai số nguyên làm đối số. Vì vậy, tôi không thấy hiệu suất thời gian chạy sẽ thay đổi rất nhiều theo cách nào. Điều này nghe có vẻ nghi ngờ như một tối ưu hóa sớm. –

Trả lời

3

Tôi sẽ sử dụng tùy chọn đầu tiên. Tác động hiệu suất của việc truyền hai số nguyên là không đáng kể. Trình tối ưu hóa cũng sẽ có thể nội tuyến cuộc gọi hàm trong trường hợp đó sẽ không có sự khác biệt giữa hai. Tùy chọn thứ hai tôi nghĩ là một ý tưởng tồi, vì bạn sẽ tạo nhiều phiên bản của cùng một hàm, không có lý do gì.

+0

Ok, có một sửa đổi nhỏ trong cú pháp câu hỏi. Bản thân 'log' là một hàm' template', tôi nghĩ không nhắc đến nó ...nhưng thấy rằng nó sẽ hữu ích. Ngoài ra, sẽ không trình biên dịch sẽ tối ưu hóa đi một số phiên bản của 'mẫu log' quá? – iammilind

+0

Cũng sẽ chỉ có một vài phiên bản của hàm log đầu tiên, std :: string, std :: wstring, char *, wchar_t *. Trong khi về cơ bản, mọi cuộc gọi hàm đến phiên bản thứ hai sẽ dẫn đến một hàm mới. Trình tối ưu hóa có thể sẽ xử lý nó, nhưng bạn sẽ nhận được kết quả tương tự với thời gian biên dịch dài hơn. – ronag

4

Vì sự lựa chọn giữa hai điều này tạo sự khác biệt cho mã gọi điện, tôi khuyên bạn nên đăng nhập qua macro. Sau đó, bạn không cần phải lo lắng về điều này là tốt hơn, bởi vì nó dễ dàng chuyển đổi giữa chúng.

Khi bạn đã viết ứng dụng thực sự của mình, bạn có thể gây rối với định nghĩa macro để so sánh hai. Hay không, nếu có nhiều lĩnh vực hiệu quả hơn để tối ưu hóa. Nếu nó tạo ra sự khác biệt lớn, bạn thậm chí có thể để nó mở cho cấu hình xây dựng để quyết định có sử dụng -DLOGGING_COMPILES_QUICKLY hoặc -DLOGGING_RUNS_QUICKLY hay không.

Một lợi ích tiềm năng khác của macro: bạn có thể sắp xếp đối số đầu tiên được đánh giá nếu và chỉ khi debug là đúng. Tôi không biết giao diện của str là gì, hoặc nơi các đối tượng đó đến từ đó, nhưng nếu nó tốn bất cứ thứ gì để tạo ra giá trị phù hợp để chuyển đến log, và sau đó log không sử dụng nó trong trường hợp không gỡ lỗi, thì đó là một sự lãng phí tiềm năng của thời gian chạy.

+0

Câu trả lời hay ... Hầu hết các lần LINE & COUNT sẽ không được sử dụng. Lựa chọn nào tốt hơn trong trường hợp mã sản xuất linh sam đó? – iammilind

+0

@iammilind: Nếu 'debug' là hằng số biên dịch, và lệnh gọi là 'log' được gạch chân, thì mã được phát ra có lẽ cũng giống nhau, mặc dù đó là vấn đề QOI. Nếu bạn muốn biết chi tiết về việc triển khai cụ thể, hãy kiểm tra việc tháo gỡ. –