2016-03-31 13 views
5

C++ 'da bitly operatörleri genellemek istiyorum ki, temel yapı bir dizidir. Mesela olarakDepolama/çalışma süresi algoritmasını optimize etmek için meta programlama, C++

... Ben 86 bit temsil etmek istiyorum ben böyle bir yapı, yapı/sınıfını kullanın: i 160 bit ayırmaya isterseniz diye böyle bir yapıyı kullanmak istiyorsunuz yerine

typedef struct { 
uint64_t x[1]; 
uint16_t y[1]; 
uint8_t z[1]; 
} sampleStruct; 

:

typedef struct { 
uint64_t x[2]; 
uint32_t y[1]; 
} sampleStruct; 

Depolama için en ufak bir çözüm değil, en uygun çözüm, tüm parçaların tekdüze olduğunu varsaymak ve bu st. Uyguladığım boyutu kapsamaktadır, ancak bir egzersiz için bile maruz kaldığım yolu tercih ederim. Bana göre

ben sorunu çözmek için metaprogramming kullanması gerektiğini açıkça sesler, bu yüzden bu yüzden anlamak istiyorum C++ şablon metaprogramlama üzerinde büyük uzmanı değilim ancak düzgün

template <int I> 
typedef sampleStruct { 
    //something 
} 

tanımlamak zorunda ne elde etmek ne yapabilirim

N64 = I/64; 
RemN = I%64; 
if(0 < RemN <= 8) { 
    add uint8_t var; 
} else if (8 < RemN <= 16) { 
    add uint16_t var; 
} else if (16 < RemN <= 24) { 
    add uint16_t var; 
    add uint8_t var; 
} else { 
    //Similarly handle the other cases from 24 < RemN < 64 
} 

: ya ben böyle bir şey olurdu benim uzunluğu için en iyi "kapağı" karar bilen örnek yapı varing I'in farklı tür uygulamak için en iyi yol olacağını Ben yapmak istiyorum?

Ayrıca, parçaların doğru bir şekilde kümelenmesinin diğer olası uygulamalara kıyasla biraz daha iyi bir performans elde etmesine izin vereceğini tahmin ediyorum.

Yeterli açıklık getiriyor ... (C++ 11 veya daha yeni sürümleri varsayarsak).

+7

İstediğiniz gibi geliyor ['std :: bitset'] (http://en.cppreference.com/w/cpp/utility/bitset). – Daniel

+0

Var olduğunu bilmiyordum, anlattığım şekilde çalışıyor mu? (depolamayı kastediyorum). – user8469759

+0

Bunun hakkında bir konuşma var: https://www.youtube.com/watch?v=ea5DiCg8HOY –

cevap

0

Bu mümkün, ancak yazımla ilgili bir miktar yazım var. Sorun C++ için bir yol sağlamaz meta-programlı bir veri elemanı ihmal (örneğin Conditional Inclusion/Exclusion of Data Members Inside Class Templates bakınız), böylece bunun varlığına veya yokluğuna uzmanlaşmış gerekir: toplam

template<int N64, bool P32, bool P16, bool P8> 
struct sampleStructImpl; 

template<int I> 
using sampleStruct = sampleStructImpl<I/64, (I%64 >= 32), (I%32 >= 16), (I%16 >= 8)>; 

çeşitli kısmi uzmanlık (8 sıfır uzunluklu diziler yasadışı olduğundan size N64 sıfır olmaya uzmanlaşmak gerekecek I az 64 den değerlerini izin edebilmek istiyorsanız, Ayrıca

template<int N64> 
struct sampleStructImpl<N64, true, true, true> 
{ 
    std::uint64_t x[N64]; 
    std::uint32_t y; 
    std::uint16_t z; 
    std::uint8_t w; 
}; 

template<int N64> 
struct sampleStructImpl<N64, true, true, false> 
{ 
    std::uint64_t x[N64]; 
    std::uint32_t y; 
    std::uint16_t z; 
    // omit std::uint8_t w; 
}; 

// 6 more partial specializations... 

:) aşağıdaki gibi görünecektir

template<> 
struct sampleStructImpl<0, true, true, true> 
{ 
    // omit std::uint64_t x[0]; 
    std::uint32_t y; 
    std::uint16_t z; 
    std::uint8_t w; 
}; 

// 7 more specializations... 

std::array<std::uint8_t, (I + 7)/8> kullanmak, muhtemelen bir alignas değiştiricisiyle 64 bit hizalamak için çok daha kolay olurdu. öyle (Eğer bit belirtildiği gibi

template <int I> 
struct sampleStruct { 
    std::uint8_t v[(I % 8)? (I/8) + 1 : (I/8)]; 
}; 

, sana bireysel üye x,y,z erişmek olmadığını farz ediyorum:

0

örneğin, uint8_t sadece bir dizi kullanmak kolay olmaz altta yatan bitlere nasıl ulaşacağınız sorusundan net değil.)

Size de istediğini yapmak mümkün, ama aşağıdaki gibi, devralma kullanmak zorunda:

template <int I> 
struct largeBlock { 
    std::uint64_t x[I]; 
}; 
template <> 
struct largeBlock<0> { 
}; 

template <int I> 
struct mediumBlock { 
    std::uint16_t y[I]; 
}; 
template <> 
struct mediumBlock<0> { 
}; 

template <int I> 
struct smallBlock { 
    std::uint8_t z[(I/8) + ((I % 8) ? 1 : 0) ]; 
}; 
template <> 
struct smallBlock<0> { 
}; 

template <int I> 
struct sampleStruct : largeBlock<I/64>, mediumBlock<(I % 64)/16>, smallBlock<(I % 16)> { 

}; 

Şimdi operasyon üssü nesnelere aramaları açısından uygulanması gerekir ...

+0

Kesinlikle ne yapmak istediğimi elde etmeyi sağlar, depolama açısından gereken minimum olur. Ancak, bir vardiya işletmecisini örnek olarak uygulamak istiyorsanız, hesaplama farkı olacaktır. – user8469759

+0

Yukarıdaki yaklaşım aynı zamanda depolama için etkilidir (daha sonra ne yaptığınızdır), kurulumunuz ve dolgularınız ile yapılarınız oldukça geniş olacaktır (örneğin 86 bit ve 11 bit için 16 bayt) - bu nedenle depolama optimizasyonu için yukarıdakiler çok zor yenmek için .. Eğer çalışma zamanı çalışma maliyetini düşünmek için sorunuzu yeniden yazıyorsanız, o zaman bu da mümkün .. – Nim

+0

Neden 86 bitlik uygulama 16 bit kullanacak? 64 + 16 + 8'dir, yani 8 + 2 + 1 bayt = 11 bayttır. Çok büyük yapıları düşünüyordum, bir sınır davası alırsanız, diyelim ki, 128 uint8_t'ye karşı 16 uint64_t değişkenine ihtiyacım var, 1024 bit, 128 uint8_t'ye karşı 16 uint64_t değişkeni üzerinde döngüsüyeceğim 1 bitlik bir sağa kayma yapıyorum, sanırım 8 bit yığın üzerinde yaptığınız her optimizasyon, bu durumda 64 bit yığınta aynı olacaktır. Bir başka önemsiz vaka ... 8 bayt ayırmak istediğinizi varsayalım, sizin durumunuza göre 4 bayt kullanırsınız, doğru muyum? Bu daha mı yoksa eşdeğer mi? – user8469759