2012-11-20 109 views
12

में संकलन-समय निरंतर मानों की static_assert स्ट्रिंगफिकेशन संकलन समय पर constexpr या #define डी मान के मूल्य को मुद्रित करने का कोई तरीका है? मैं std::cout << के बराबर, या किसी तरह की तरह कुछ करना चाहता हूँstd :: cout compile time पर समकक्ष, या C++ 11

constexpr int PI_INT = 4; 
static_assert(PI_INT == 3, 
       const_str_join("PI_INT must be 3, not ", const_int_to_str(PI_INT))); 

संपादित करें: मैं कुछ बुनियादी संकलन समय constexpr रों साथ मुद्रण, कम से कम जीसीसी पर

template <int v> 
struct display_non_zero_int_value; 

template <> 
struct display_non_zero_int_value<0> { static constexpr bool foo = true; }; 

static constexpr int v = 1; 

static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0"); 
की तरह कुछ कर रही द्वारा कर सकते हैं

जो मुझे error: incomplete type ‘display_non_zero_int_value<1>’ used in nested name specifier static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0"); देता है। (Icpc, दूसरे हाथ पर, कम उपयोगी है, और सिर्फ error: incomplete type is not allowed कहते हैं) वहाँ एक रास्ता एक मैक्रो है कि इस सामान्यीकरण करूँ ताकि तरह

constexpr int PI_INT = 4; 
PRINT_VALUE(PI_INT) 

कुछ करना और एक त्रुटि संदेश है कि शामिल है प्राप्त कर सकते हैं लिखने के लिए है 4, किसी भी तरह?

+2

इसे उत्तर के रूप में पोस्ट नहीं किया जा रहा है क्योंकि मेरे पास हाथों का सबूत नहीं है, लेकिन मुझे याद है कि अतीत में ऐसा करने की कोशिश कर रहा है और मुझे लगता है कि मानक कहता है कि static_assert को एक स्ट्रिंग अक्षरना है, और इसके परिणामस्वरूप आप कर सकते हैं इसके बजाय एक constexpr अभिव्यक्ति का उपयोग नहीं करते हैं। माफ़ कीजिये। – je4d

+0

ध्यान दें कि आपका फ़िक्स वास्तव में 'static_assert' का उपयोग नहीं कर रहा है। यह सिर्फ एक निर्माण के मूल विचार को पुनर्निर्मित कर रहा है जो पास या असफल होने के अलावा कुछ भी नहीं करता है। "प्रिंटिंग" की चीज को भी परीक्षण करना पड़ता है, इसलिए आप पूरी समस्या को SFINAE के साथ हल कर रहे हैं। – Potatoswatter

उत्तर

11

§7/​​1 [dcl.dcl] में व्याकरण घोषणाओं के लिए दिए गए का हवाला देते हुए:

static_assert-declaration:

static_assert (constant-expression , string-literal) ;

मानक कहते हैं कि यह एक स्ट्रिंग शाब्दिक होने के लिए है, तो आप भाग्य से बाहर हो गया है; आप अपने त्रुटि संदेश को बनाने के लिए एक constexpr फ़ंक्शन का उपयोग नहीं कर सकते हैं।

हालांकि, आप जो भी प्रीप्रोसेसर जादू का उपयोग कर सकते हैं, वहां आप वहां जाने के लिए एक स्ट्रिंग अक्षर उत्पन्न करना चाहते हैं। यदि PI_INT एक #define एक constexpr int के बजाय है, तो आप कुछ इस तरह इस्तेमाल कर सकते हैं:

#define PI_INT 4 
#define pi_err_str_(x) #x 
#define pi_err_str(x) pi_err_str_(x) 
#define pi_int_err "PI_INT must be 3, not " pi_err_str(PI_INT) 

static_assert(PI_INT == 3, pi_int_err); 

उत्पादन:

error: static assertion failed: "PI_INT must be 3, not 4"


ओपी द्वारा टिप्पणी के जवाब में संपादित और अद्यतन सवाल

Is there a way to write a macro that can generalize this so that I can do something like ... and get an error message that involves 4, somehow?

निश्चित रूप से, प्रीप्रोसेस का थोड़ा सा या जादू कि सामान्यीकरण कर सकते हैं, यह मानते हुए आप संकलक-विशिष्ट त्रुटि संदेश व्यवहार पर निर्भर होने के लिए खुश हैं:

#define strcat_(x, y) x ## y 
#define strcat(x, y) strcat_(x, y) 
#define PRINT_VALUE(x) template <int> struct strcat(strcat(value_of_, x), _is); static_assert(strcat(strcat(value_of_, x), _is)<x>::x, ""); 

constexpr int PI_INT = 4; 
PRINT_VALUE(PI_INT) 

stackoverflow/13465334.cpp:20:1: error: incomplete type ‘value_of_PI_INT_is<4>’ used in nested name specifier

अन्य compilers के रूप में, मैं तुम्हें बेतकल्लुफ़ क्या कर सकते हैं पता नहीं है, लेकिन आप हो सकता है कि बूस्ट की static_assert.hpp की एक प्रति को देखना चाहें कि वहां नियोजित किसी भी चाल का उपयोग मूल्यांकन किए गए टेम्पलेट तर्क को मुद्रित करने के लिए किया जा सकता है या नहीं।

+0

जो मेरे प्रश्न के अंतिम दो-तिहाई उत्तर देता है। संकलन समय पर 'constexpr' मान छपाई के बारे में पहला तीसरा, स्पष्ट नहीं है। मैंने जो संपादन किया है उसे देखें। –

+0

ब्लॉक स्कोप पर काम करने के लिए इसका कोई तरीका (टेम्पलेट किए गए कार्यों के अंदर प्रिंटिंग के लिए)? – mxmlnkn