2013-05-25 25 views
7

मैं संकलन समय पर निर्धारित करने का प्रयास कर रहा हूं यदि std::initializer_list में सभी मान अद्वितीय हैं। मैं एक सूची के valiate the size के समाधान का पता लगाने में सक्षम था लेकिन सामग्री पर इसे लागू करने में असमर्थ रहा हूं। मैंने दोनों मुफ्त कार्यों और रचनाकारों के साथ प्रयास किया है लेकिन दोनों दृष्टिकोणों के परिणामस्वरूप जीसीसी 4.7.2 के साथ निम्नलिखित त्रुटियां हुई हैं।संकलन समय पर std :: startizer_list की सामग्री मान्य करें

error: non-constant condition for static assertion
error: 'begin' is not a constant expression

मुझे पता std::initializer_list के सदस्यों constexpr घोषित नहीं कर रहे हैं, लेकिन मैं आशा करती हूं कि वहाँ आकार मान्यता की तरह एक समाधान है। क्या निम्न की तरह कुछ का उपयोग करके संकलित समय पर सामग्री को सत्यापित करना संभव है?

#include <initializer_list> 

template<typename InputIterator> 
constexpr bool Validate(InputIterator begin, InputIterator end) 
{ 
    static_assert(*begin == *end, "begin and end are the same"); 
    // The actual implemetnation is a single line recursive check. 
    return true; 
} 

template<typename InputType> 
constexpr bool Validate(const std::initializer_list<InputType>& input) 
{ 
    // "-1" removed to simplify and eliminate potential cause of error 
    return Validate(input.begin(), input.end() /* - 1 */); 
} 

int main() 
{ 
    Validate({1, 2, 1}); 
} 
+2

के लिए वर्तमान प्रस्ताव के अनुसार [सी ++ 14] (http://isocpp.org/files/papers/N3690.pdf), 'शुरू()' और ' 'std :: startizer_list' का अंत() 'भविष्य में' constexpr' होगा (18.9/1 देखें)। इससे एक बाधा दूर हो जाती है, लेकिन मुझे यकीन नहीं है कि संकलन समय पर पुनरावर्तक मानों को संदर्भित करना संभव होगा या नहीं। – jogojapan

+1

@jogojapan: 'std :: startizer_list ' "iterators" केवल 'T *' - गारंटीकृत हैं। – Xeo

+0

@Xeo हां, और मैंने माना कि इस तरह के सूचक को निरंतर अभिव्यक्ति में अनुमति नहीं दी जाएगी। – jogojapan

उत्तर

1

कुछ खुदाई यह std::initializer_list का उपयोग कर की तरह लग रहा करने के बाद यह घोषणा में constexpr की कमी के कारण नहीं जीसीसी 4.7 में संभव है। यह जीसीसी 4.8 के साथ <initializer_list> के साथ काम constexpr शामिल करने के लिए अद्यतन किया गया है। दुर्भाग्य से जीसीसी 4.8 का उपयोग इस समय एक विकल्प नहीं है।

किसी भी सरणी के तत्वों को एक्सेस करना संभव है यदि क्षय पॉइंटर संदर्भ द्वारा पारित किया गया हो। यह सत्यापन को वांछित होने की अनुमति देता है लेकिन अभी भी वह समाधान नहीं है जिसके लिए मैं उम्मीद कर रहा हूं। निम्नलिखित कोड सरणी के लिए एक व्यावहारिक समाधान है। यह अभी भी आवश्यक है कि सरणी का आकार सत्यापन समारोह में प्रदान किया जाए लेकिन यह सही करने के लिए पर्याप्त आसान है।

#include <initializer_list> 

template<typename T> 
constexpr bool Compare(T& data, int size, int needleIndex, int haystackIndex) 
{ 
    return 
     needleIndex == haystackIndex ? 
      Compare(data, size, needleIndex + 1, haystackIndex) 
     : needleIndex == size ? 
       false 
      : data[needleIndex] == data[haystackIndex] ? 
        true 
       : Compare(data, size, needleIndex + 1, haystackIndex); 
} 

template<typename T> 
constexpr bool Compare(T& data, int size, int index) 
{ 
    return 
     index == size ? 
      false 
     : Compare(data, size, index + 1) ? 
       true 
      : Compare(data, size, 0, index); 
} 


template<typename T, int ArraySize> 
constexpr bool Validate(T(&input)[ArraySize], int size) 
{ 
    return !Compare(input, size, 0); 
} 

int main() 
{ 
    constexpr int initData0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
    constexpr int initData1[] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
    constexpr int initData2[] = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
    constexpr int initData3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 8}; 
    constexpr int initData4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 7}; 
    constexpr int initData5[] = {0, 1, 0, 3, 4, 5, 6, 7, 8, 9}; 
    constexpr int initData6[] = {0, 1, 2, 3, 4, 5, 6, 9, 8, 9}; 

    static_assert(Validate(initData0, 10), "set 0 failed"); // <-- PASS 
    static_assert(Validate(initData1, 10), "set 1 failed"); // <-- (and below) FAIL 
    static_assert(Validate(initData2, 10), "set 2 failed"); 
    static_assert(Validate(initData3, 10), "set 3 failed"); 
    static_assert(Validate(initData4, 10), "set 4 failed"); 
    static_assert(Validate(initData5, 10), "set 5 failed"); 
    static_assert(Validate(initData6, 10), "set 6 failed"); 
} 

बिल्ड लॉग:

C:\Source\SwitchCaseString\main.cpp: In function 'int main()':
C:\Source\SwitchCaseString\main.cpp:198:2: error: static assertion failed: set 1 failed
C:\Source\SwitchCaseString\main.cpp:199:2: error: static assertion failed: set 2 failed
C:\Source\SwitchCaseString\main.cpp:200:2: error: static assertion failed: set 3 failed
C:\Source\SwitchCaseString\main.cpp:201:2: error: static assertion failed: set 4 failed
C:\Source\SwitchCaseString\main.cpp:202:2: error: static assertion failed: set 5 failed
C:\Source\SwitchCaseString\main.cpp:203:2: error: static assertion failed: set 6 failed

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