2015-08-14 13 views
5

Chúng tôi chỉ mới bắt đầu học mẫu lập trình meta trong C++ 11. Như một bài tập, chúng tôi đã viết một chương trình xuất kết quả đại diện nhị phân của một giá trị int. Chúng tôi đã đưa ra hai triển khai có thể. Việc đầu tiên sử dụng đệ quy với các giá trị enum trong khi phương pháp thứ hai sử dụng một hàm constexpr.Metaprogramming với constexpr hoặc struct

kỳ vọng của chúng tôi là cả hai kết quả thực hiện trong thực thi có cùng kích thước. Tuy nhiên, việc thực hiện đầu tiên dẫn đến 9064 byte trong khi lần thứ hai có 9096 byte. Chúng tôi không nhớ sự khác biệt nhỏ trong byte nhưng không hiểu những gì gây ra sự khác biệt.

Chúng tôi biên soạn chương trình với GCC 4.8.2 mà không cờ tối ưu hóa, tuy nhiên, kết quả tương tự được tìm thấy lá cờ -O2.

#include <iostream> 
using namespace std; 

template <int val> 
struct Bin 
{ 
    enum { value = 10 * Bin<(val >> 1)>::value + (val & 1) }; 
}; 

template <> 
struct Bin<0> 
{ 
    enum { value = 0 }; 
}; 

constexpr int bin(int val) 
{ 
    return val == 0 ? 0 : (10 * bin(val >> 1) + (val & 1)); 
} 


int main() 
{ 
    // Option 1 
    cout << Bin<5>::value << '\n' 
     << Bin<27>::value << '\n'; 

    // Option 2 
    cout << bin(5) << '\n' 
     << bin(27) << '\n'; 
} 
+0

Chương trình này trông đơn giản đủ để Thao thiêt và phân tích. – Borsunho

+4

'hàm constexpr' không được đảm bảo để được đánh giá tại thời gian biên dịch trừ khi được sử dụng trong ngữ cảnh yêu cầu một biểu thức không đổi. –

Trả lời

3

constexpr chức năng thể được đánh giá tại thời gian biên dịch. Họ không được yêu cầu.

Đối với mã mà bạn cung cấp, trình biên dịch không thực sự làm điều đó và bin là nhận được gọi trong thời gian chạy; điều này có nghĩa là không thể vứt bỏ chức năng khỏi hội đồng. Bằng cách yêu cầu một cách rõ ràng các giá trị được constexpr với

constexpr auto i = bin(5), j = bin(27); 

các cuộc gọi đến bin được thực hiện tại thời gian biên dịch như here. Với

cout << bin(5) << '\n' 
     << bin(27) << '\n'; 

mã phát ra có liên quan là

movl $5, %edi # Parameter 
callq bin(int) # Here's the call to bin 
movl std::cout, %edi 
movl %eax, %esi 
callq std::basic_ostream<char, std::char_traits<char> >::operator<<(int) 
[...] 
movl $27, %edi # parameter 
callq bin(int) # call to bin 
movq %rbx, %rdi 
movl %eax, %esi 
callq std::basic_ostream<char, std::char_traits<char> >::operator<<(int) 

Khi cuộc gọi được elided, kích thước là như nhau cho cả hai phiên bản.

+0

Cảm ơn bạn đã trả lời. Có cách nào để yêu cầu rõ ràng các giá trị là 'constexpr' mà không lưu trữ chúng vào một biến không? – Michiel

+0

@MichielUitHetBroek Cách sẵn để buộc 'chức năng constexpr' được đánh giá tại thời gian biên dịch cần thêm mã hóa (thường được tối ưu hóa ra) và đơn giản nhất là sử dụng một giá trị thời gian biên dịch. Xem [this] (https://stackoverflow.com/questions/14248235/when-does-a-constexpr-function-get-evaluated-at-compile-time?rq=1) và liên quan. – edmz

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