2011-08-05 8 views
6

मेरे पास एक सरणी है जिसका उपयोग T:मैं alignas (टी) अनुकरण कैसे कर सकते हैं?

char memory[sizeof T]; 
. 
. 
. 
new(memory) T(whatever); 

की ऑब्जेक्ट की अंतर्निहित स्मृति के रूप में किया जाता है। मैं कैसे सुनिश्चित कर सकता हूं कि T ऑब्जेक्ट्स T ऑब्जेक्ट्स के लिए सही ढंग से संरेखित है? सी ++ 0x में मैं बस कह सकता हूं:

alignas(T) char memory[sizeof T]; 

लेकिन विजुअल स्टूडियो 2010 अभी तक उस विशेष सुविधा का समर्थन नहीं करता है।

उत्तर

10

सामान्य (पोर्टेबल) समाधान T में जो भी अंतर्निहित प्रकार है, उसके साथ यूनिट में मेमोरी घोषणा को रखना है, सबसे संरेखण की आवश्यकता है। सबसे आसान तरीका संभावना उम्मीदवारों के सभी के साथ एक संघ का उपयोग करने के होगा:

union MaxAlign 
{ 
    int     i  ; 
    long    l  ; 
    long long   ll ; 
    long double   ld ; 
    double    d  ; 
    void*    p  ; 
    void (*    pf)() ; 
    MaxAlign*   ps ; 
} ; 

union 
{ 
    MaxAlign dummyForAlignment; 
    unsigned char memory[sizeof(T)]; 
} rawT; 

मैं के बारे में बहुत कम मुठभेड़, एक मशीन जहां ऊपर पर्याप्त नहीं था सुनने के लिए अभी तक है। आम तौर पर, बस double पर्याप्त है। (यह निश्चित रूप से इंटेल और स्पार्क पर पर्याप्त है।)

कुछ चरम मामलों में, इसका परिणाम से अधिक मेमोरी आवंटित करने के परिणामस्वरूप हो सकता है, उदा। यदि T में केवल एक या दो char शामिल हैं। अधिकांश समय, यह वास्तव में कोई फर्क नहीं करता, और के बारे में चिंता के लायक नहीं है, लेकिन अगर यह है, निम्नलिखित इस्तेमाल किया जा सकता:

namespace MyPrivate { 

template< typename T, bool isSmaller > 
struct AlignTypeDetail ; 

template< typename T > 
struct AlignTypeDetail< T, false > 
{ 
    typedef T type ; 
} ; 

template< typename T > 
struct AlignTypeDetail< T, true > 
{ 
    typedef char type ; 
} ; 

template< typename T, typename U > 
struct AlignType 
{ 
    typedef typename AlignTypeDetail< U, (sizeof(T) < sizeof(U)) >::type 
         type ; 
} ; 
} 

template< typename T > 
union MaxAlignFor 
{ 
    typename MyPrivate::AlignType< T, char >::type  c ; 
    typename MyPrivate::AlignType< T, short >::type  s ; 
    typename MyPrivate::AlignType< T, int >::type   i ; 
    typename MyPrivate::AlignType< T, long >::type  l ; 
    typename MyPrivate::AlignType< T, long long >::type ll ; 
    typename MyPrivate::AlignType< T, float >::type  f ; 
    typename MyPrivate::AlignType< T, double >::type  d ; 
    typename MyPrivate::AlignType< T, long double >::type ld ; 
    typename MyPrivate::AlignType< T, void* >::type  pc ; 
    typename MyPrivate::AlignType< T, MaxAlign* >::type ps ; 
    typename MyPrivate::AlignType< T, void (*)() >::type pf ; 
} ; 

इस मामले में, MaxAlignFor<T> से भी बड़ा कभी नहीं होगा T (और पर्याप्त संरेखण होने के लिए, क्योंकि आवश्यक संरेखण T के आकार से बड़ा नहीं होगा)।

ध्यान दें कि इनमें से कोई भी औपचारिक रूप से मानक द्वारा गारंटीकृत नहीं है। लेकिन यह अभ्यास में काम करेगा।

+0

आपका मतलब 'enum' के बजाय 'संघ' है, है ना? – fredoverflow

+0

हां। उदाहरणों ने स्पष्ट किया, मुझे उम्मीद है। –

+0

@ मेहरदाद यह कहता है कि वीसी ++ एक निश्चित सुविधा का समर्थन नहीं करता है। यह नहीं कहता कि यह एकमात्र कंपाइलर था। –

5

vc++ align के लिए गुगलिंग this page दिखाता है: __declspec(align(#)) का उपयोग करें।

+4

जो अग्रणी '__' स्पष्ट रूप से इंगित करता है, एक कंपाइलर विशिष्ट एक्सटेंशन है। –

+1

@JamesKanze: यह 3 साल देर हो चुकी है, लेकिन मैं इसे किसी भी तरह का उल्लेख करूंगा ... यह प्रश्न में दृश्य सी ++ कहता है :) – Mehrdad

+0

@JamesKanze: क्षमा करें, मैंने वास्तव में अपने फोन के साथ टिप्पणी की और मुझे एहसास नहीं हुआ कि मैं ' गलत पोस्ट पर टिप्पणी कर रहा हूँ। आपकी पोस्ट के तहत मेरा जवाब यहां आपकी टिप्पणी के जवाब में होना था। – Mehrdad

2

या तो ढेर पर स्मृति आवंटित करें (जिसमें संरेखण गारंटी है) या boost::aligned_storage का उपयोग करें।

3

हैं टी एक मानक लेआउट है और संघ में अच्छी तरह से बनाई है, तो

union 
{ 
    T t; 
    char memory[sizeof T]; 
}; 

गठबंधन किया जाना चाहिए।