2016-02-04 33 views
6

के आकार को static_assert कैसे करें, मैं किसी सदस्य चर पर सरणी आकार प्रतिबंधों के बारे में स्पष्ट होना चाहता हूं, ताकि दूसरों को गलती से मूर्ख परिवर्तन करने से रोक सकें। निम्नलिखित अनुभवहीन प्रयास संकलन नहीं:std :: array सदस्य

struct Foo 
{ 
    std::array< int, 1024 > some_array; 
    static_assert((some_array.size() % 256) == 0, "Size must be multiple of 256"); 
    //^ (clang) error: invalid use of non-static data member 'some_array' 
}; 

भी std::array::size हालांकि एक constexpr है, मैं सीधे static_assert उस तरह उपयोग नहीं कर सकते न समारोह न ही मेरे सदस्य चर स्थिर है, क्योंकि।

समाधान मैं के साथ उपयोग करने के लिए है आया decltype इस प्रकार है (के बाद से मैं सरणी typedef नहीं करना चाहती):

static_assert((decltype(some_array)().size() % 256) == 0, "Size must be multiple of 256"); 

यह लग रहा है यह है की तरह डिफ़ॉल्ट-निर्माण एक rvalue, जो मैं नहीं सोचा constexpr है।

यह क्यों काम करता है?

क्या स्थिर दावा प्राप्त करने के लिए कोई क्लीनर तरीका है?

+0

आपका समारोह मुझे सर o.o के लिए ठीक काम करता है, Vusal स्टूडियो में। – Jts

+0

'(घोषणा () आकार()% 256) == 0' काम नहीं करता है? –

उत्तर

5

क्योंकि न तो फ़ंक्शन और न ही मेरा सदस्य चर स्थिर है।

दाएं। समस्या यह है कि स्थैतिक जोर एक गैर स्थैतिक सदस्य का संदर्भ नहीं दे सकता है, क्योंकि some_array.size()this->some_array.size() के बराबर है और कक्षा स्कोप पर केवल this पॉइंटर नहीं है (केवल फ़ंक्शन घोषणाकर्ताओं और डिफ़ॉल्ट सदस्य प्रारंभकर्ताओं के अंदर)।

हालांकि, यह decltype(array_size) कहने के लिए है, क्योंकि है कि वास्तव में वस्तु array_size को देखें या अपने सदस्य कार्यों को लागू करने की कोशिश नहीं कर रहा है ठीक है, यह सिर्फ एक नाम कक्षा में घोषित के प्रकार की क्वेरी है।

ऐसा लगता है कि यह डिफ़ॉल्ट रूप से एक रैवल्यू का निर्माण कर रहा है, जिसे मैंने नहीं सोचा था।

array<int, N> एक शाब्दिक प्रकार है, इसलिए निरंतर अभिव्यक्तियों में बनाया जा सकता है। तथ्य यह है कि आप एक रावल्यू बना रहे हैं इससे कोई फर्क नहीं पड़ता, आप एक शाब्दिक प्रकार का निर्माण कर सकते हैं और निरंतर अभिव्यक्ति में एक कॉन्स्टेक्स सदस्य फ़ंक्शन को कॉल कर सकते हैं।

array<std::string, N> जैसे कुछ का उपयोग नहीं किया जा सका, क्योंकि std::string एक शाब्दिक प्रकार नहीं है, और इसलिए न तो array<string, N> है।

क्या स्थिर दावा प्राप्त करने के लिए कोई क्लीनर तरीका है?

मानक विशेषता std::tuple_sizestd::array के लिए विशेष है, ताकि आप कर सकते हैं:

static_assert(std::tuple_size<decltype(some_array)>::value % 256) == 0, 
       "Size must be multiple of 256"); 
7

std::array::sizeconstexpr है और, static_assert साथ काम करना चाहिए लेकिन यह इस विशेष संदर्भ (जैसे कि, वर्ग परिभाषा) में काम नहीं करता क्योंकि some_array एक गैर स्थिर सदस्य चर रहा है।

इस विशेष संदर्भ आप एक घर बनाया प्रकार विशेषता इस्तेमाल कर सकते हैं नीचे की तरह संकलन समय पर आकार लेने के लिए के लिए:

template<typename> 
struct array_size; 

template<typename T, std::size_t N> 
struct array_size<std::array<T, N>> { 
    static const std::size_t size = N; 
}; 

और static_assert के रूप में:

static_assert(array_size<decltype(some_array)>::size % 256) == 0, "Size must be multiple of 256"); 

Live Demo

+1

ऐसा लगता है कि आप मिश्रित प्रकार और मूल्य मेटाफंक्शन हैं :) – Quentin

+0

यह इस प्रकार है कि मुझे उम्मीद है कि 'std :: array' लागू किया जाएगा ... क्यों टेम्पलेट के आकार मान तक सीधे पहुंच नहीं है? लेकिन यह मामला नहीं है। हालांकि यह एक अच्छा समाधान है, मुझे यकीन नहीं है कि यह वास्तव में "क्लीनर" है, क्योंकि ऐसा लगता है कि इसे और भी ढांचे की आवश्यकता है। – paddy

+0

@ 101010 कभी नहीं, मैंने सवाल को गलत तरीके से पढ़ा। – juanchopanza

संबंधित मुद्दे