2015-08-14 29 views
5

C++ 11'de şablon meta programlamayı öğrenmeye başladık. Bir egzersiz olarak, bir int değerinin ikili temsilini veren bir program yazdık. İki olası uygulama ile geldik. Birincisi enum değerleri ile özyinelemeyi kullanırken, ikinci yöntem bir constexpr fonksiyonu kullanmaktadır.Constexpr veya struct ile metaprogramlama

Bizim beklentimiz her iki uygulamanın da aynı boyutta çalıştırılabilir sonuçlarla sonuçlanmasıydı. Bununla birlikte, ilk uygulama 9064 bayta, ikincisi ise 9096 bayta ulaşır. Baytlardaki küçük farkı önemsemeyiz, ancak farkın nedenini anlamıyoruz.

Programı GCC 4.8.2 ile optimizasyon bayrağı olmadan derledik, ancak aynı sonuçları -O2 bayrağı bulduk.

#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

Bu program, dağıtmak ve analiz etmek için yeterince basit görünüyor. – Borsunho

+4

'constexpr' işlevlerinin, sabit bir ifade gerektiren bir bağlamda kullanılmadığı sürece derleme zamanında değerlendirilmeleri garanti edilmez. –

cevap

3

constexpr fonksiyonları derleme zamanında değerlendirilebilir olabilir. Onlar için gerekli değildir.

Sağladığınız kod için derleyici bunu gerçekten yapmıyor ve bin çalışma zamanında çağrılıyor; Bu, fonksiyonun montajdan atılamayacağı anlamına gelir. açık here gösterildiği gibi bin çağrıları derleme zamanında yapılır constexpr

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

olmak değerlerin gerekmesiyle.

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

ile ilgili yayılan kod

çağrı birşeyler eksik olur
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) 

, boyut iki versiyonu için aynı olmasıdır.

+0

Cevabınız için teşekkür ederiz. Değerleri bir değişkene saklamaksızın açıkça 'constexpr' olmasını gerektiren bir yol var mı? – Michiel

+0

@MichielUitHetBroek Derleme zamanında değerlendirilecek "constexpr" işlevlerini zorlamak için kullanılabilecek yollar, ek kodlama (genellikle en iyi duruma getirilmiş) gerektirir ve en kolayı bir derleme zamanı değeri kullanır. Bkz. [Https://stackoverflow.com/questions/14248235/when-does-a-constexpr-function-get-evaluated-at-compile-time?rq=1) ve ilgili. – edmz