2013-02-11 16 views
6

मैं किसी भी चीज पर स्थिर रूप से static_assert कैसे कर सकता हूं जो एक स्ट्रिंग अक्षर नहीं है?टाइप_ट्रेट्स के साथ एक स्ट्रिंग अक्षर का पता कैसे लगाएं?

उदाहरण के लिए, निम्नलिखित कोड में, मैंने मानक जोर मैक्रो को लपेटने का प्रयास किया है, लेकिन संदेश के लिए कुछ भी स्थैतिक रूप से अस्वीकार कर रहा है जो एक स्ट्रिंग शाब्दिक नहीं है (क्योंकि कुछ भी स्ट्रिंग शाब्दिक रनटाइम पर प्रदर्शित नहीं किया जाएगा जब जोर चलाता है)।

#include <cassert> 
#include <string> 
#include <type_traits> 

#define my_assert(test, message)\ 
    static_assert(\ 
     (\ 
      !std::is_pointer<decltype(message)>::value &&\ 
      !std::is_array<decltype(message)>::value\ 
     ),\ 
     "literal string required"\ 
    );\ 
    assert((message, (test))); 

int main() { 
    my_assert(1 == 1, "one equals one"); 
    my_assert(1 == 2, "one equals two"); 

    { 
     const char *msg = "one equals one"; 
     //my_assert(1 == 1, msg); // triggers static_assert 
    } 

    { 
     const char msg[] = "one equals one"; 
     //my_assert(1 == 1, msg); // triggers static_assert 
    } 

    { 
     const std::string msg = "one equals one"; 
     //my_assert(1 == 1, msg.c_str()); // triggers static_assert 
    } 

    { 
     const int msg = 3; 
     my_assert(1 == 1, msg); // should trigger static_assert 
    } 
} 

आप देख सकते हैं, परीक्षण type_traits हैडर द्वारा प्रदान की परीक्षण के माध्यम से किया जाता है, और, ज्यादातर, इस कोड काम करता है के रूप में इरादा (जीसीसी 4.7.2 के साथ परीक्षण किया)। हालांकि, यह विशेष रूप से स्ट्रिंग अक्षर की तलाश नहीं करता है जितना कि यह सामान्य चीजों को अस्वीकार करता है जो एक प्रोग्रामर स्थान पर उपयोग कर सकता है।

मेरे पास जो समाधान ऊपर है, उसके लिए पर्याप्त हो सकता है, लेकिन मैं इसका उपयोग करना चाहता हूं, या अन्य स्थितियों में भी इसी तरह की तकनीक का उपयोग करना चाहता हूं।

तो सवाल यह है कि, मैं स्ट्रिंग अक्षर को छोड़कर कुछ पर static_assert पर type_traits (या कोई अन्य मानक तंत्र) का विश्वसनीय रूप से उपयोग कैसे करूं?

+0

आप वास्तव में जब एक ज़ोर विफल रहता है एक संदेश प्रदर्शित करना चाहते हैं? यदि ऐसा है तो कृपया एक और प्रश्न पोस्ट करें। मानक 'assert() 'मैक्रो मेरी राय में बहुत बेकार है लेकिन इसमें स्वयं को लिखने के लिए वास्तव में साफ तरीके हैं, जो एक संदेश को शामिल चर के मूल्यों के साथ प्रदर्शित करते हैं। – Ali

+0

@ एली धन्यवाद, लेकिन मेरे प्रश्न के मुताबिक 'जोर()' के साथ बहुत कम करना है, यह एक कारण बताता है कि सवाल का जवाब उपयोगी हो सकता है। जब मैं gcc/libc द्वारा प्रदान किए गए मानक का उपयोग कर विफल रहता हूं तो मुझे एक अच्छा संदेश मिलता है। निश्चित रूप से दावे करने के लिए अधिक परिष्कृत तरीके हैं, लेकिन यह वास्तव में मेरे प्रश्न का मुद्दा नहीं है - जैसा कि मैंने कहा था, मुझे दिलचस्पी है कि एक स्ट्रिंग शाब्दिक बनाम अन्य चीजों का पता कैसे लगाया जाए। (नीचे मेरा स्वयं का जवाब चाल को बहुत बारीकी से लगता है।) – wjl

+0

ठीक है, हालांकि आपको एक फैंसी जोर देने की आवश्यकता है। अच्छा कामयाब हो! – Ali

उत्तर

5

यहाँ सबसे अच्छा मैं मिल सकता है, जो कुछ भी मैं इसे फेंक अस्वीकार करने के लिए प्रकट होता है, लेकिन अभी भी शाब्दिक तार स्वीकार करता है:

#define my_assert(test, message)\ 
    static_assert(\ 
     (\ 
      std::is_convertible  <decltype(message), const char *>::value &&\ 
      !std::is_rvalue_reference <decltype(message)>::value &&\ 
      !std::is_pointer   <decltype(message)>::value &&\ 
      !std::is_array   <decltype(message)>::value &&\ 
      !std::is_class   <decltype(message)>::value\ 
     ),\ 
     "string literal required"\ 
    );\ 
    assert((message, (test))) 

मैं बहुत अगर यह वास्तव में विस्तृत रूप से है पता करने के लिए दिलचस्पी होगी सही, और/या यदि इस पहचान को करने का एक आसान तरीका है।

0

'स्ट्रिंग शाब्दिक रिटर्न के "decltype (" कुछ स्ट्रिंग ")'" कॉन्स char() [n] "टाइप करें। इस प्रकार, यह लगता है कि the following answer के साथ तुलना में अधिक संक्षिप्त है, जिस तरह से यह पता लगाने के लिए:

template<typename T> 
struct IsStringLiteral : 
    std::is_same< 
     T, 
     std::add_lvalue_reference_t<const char[std::extent_v<std::remove_reference_t<T>>]> 
    > 
{}; 

(online demo)

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