2012-09-24 16 views
8

मेरे पास एक सी ++ कक्षा है जो लॉगिंग सिस्टम के लिए अग्रभाग है। इसका प्रवेश समारोह सी ++ 11 के variadic टेम्पलेट का उपयोग कर कार्यान्वित किया जाता है:सी ++ 11 वैरिएडिक टेम्पलेट्स के साथ जीसीसी के प्रिंटफ प्रारूप विशेषता का उपयोग कैसे करें?

template <typename... Args> 
void Frontend::log(const char *fmt, Args&&... args) { 
    backend->true_log(fmt, std::forward<Args>(args)...); 
} 

प्रत्येक प्रवेश बैकएंड true_log का अपना संस्करण को लागू करता है, कि अन्य बातों के अलावा, अग्रेषित पैरामीटर का उपयोग करता vsnprintf कॉल करने के लिए। उदा .:

void Backend::true_log(const char *fmt, ...) { 
    // other stuff.. 
    va_list ap; 
    va_start(ap, fmt); 
    vsnprintf(buffer, buffer_length, fmt, ap); 
    va_end(ap); 
    // other stuff.. 
} 

सबकुछ बढ़िया काम करता है, और मैं खुश हूं।

अब, मैं log() पैरामीटर पर एक स्थिर जांच जोड़ना चाहता हूं: विशेष रूप से, मैं जीसीसी के प्रिंटफ प्रारूप विशेषता का उपयोग करना चाहता हूं।

मैंने log() फ़ंक्शन को __attribute__ ((format (printf, 2, 3))) के साथ टैग करके शुरू किया (this पहला "छुपा" पैरामीटर है, मुझे पैरामीटर इंडेक्स को एक से स्थानांतरित करने की आवश्यकता है)। यह काम नहीं करता है, क्योंकि एक संकलन त्रुटि के साथ विफल करता है, तो: तो फिर

error: args to be formatted is not ‘...’ 

, मैं true_log() कार्य करने के लिए एक ही विशेषता जोड़ने की कोशिश की। यह संकलित करता है, लेकिन वास्तव में कोई त्रुटि जांच नहीं की जाती है: मैंने log() को कुछ अमान्य प्रारूप/परिवर्तनीय संयोजनों को पास करने का प्रयास किया, और कोई चेतावनी जारी नहीं की गई। हो सकता है कि इस तरह की जांच "बहुत देर हो चुकी है", या, दूसरे शब्दों में, चर के बारे में जानकारी कॉल की श्रृंखला में खो गई है?

अंतिम उपाय के रूप में, यदि मैंने log() को __attribute__ ((format (printf, 2, 0))) के साथ एनोटेट किया है, तो मुझे गलत प्रारूप तारों के बारे में चेतावनियां मिलेंगी, लेकिन अमान्य प्रारूप/परिवर्तनीय संयोजनों के लिए कोई निदान जारी नहीं किया जाएगा।

समस्या का सारांश: यदि मैं सी ++ 11 के विविध टेम्पलेट का उपयोग करता हूं तो मेरे पास जीसीसी से पूर्ण प्रारूप जांच कैसे हो सकती है?

+0

चूंकि बनामप्रिंटफ() पुराने स्कूल से अधिक से निपट नहीं सकता है ... क्या कर सकता है, पहली जगह में विविधता वाले टेम्पलेट्स से परेशान क्यों हो? –

+1

आप विविध प्रकार के टेम्पलेट्स का उपयोग क्यों कर रहे हैं जब आप केवल प्रकार की जानकारी फेंक रहे हैं? बस अपना असली लॉगिंग फ़ंक्शन 'true_log()' बनाएं। –

+0

या 'फ्रंटएंड :: लॉग' को एक परिवर्तनीय तर्क दें ... –

उत्तर

2

मुझे विश्वास नहीं है कि आप कर सकते हैं। मैं शर्त लगाता हूं कि जीसीसी केवल प्रारूप स्ट्रिंग को सत्यापित करता है यदि यह शाब्दिक है। यही कारण है कि पर format विशेषता डालने से काम नहीं होता है - उस फ़ंक्शन को रनटाइम-निर्धारित स्ट्रिंग की तरह दिखने (वाक्य रचनात्मक) के साथ बुलाया जाता है। इसे log पर डालने से सीधे उसे बाधित किया जाएगा, लेकिन format गुणों को विविधता टेम्पलेट का समर्थन करने के लिए आवश्यक होगा, जिसे आपने साबित किया है।

मेरा सुझाव है कि आप स्वरूपित आउटपुट करने के लिए अधिक C++ - ish तरीकों को देखें। उदाहरण के लिए, boost::format जो प्रिंटफ की तरह काम करता है, लेकिन गतिशील रूप से सत्यापित करता है कि पैरामीटर प्रकारों की संख्या और प्रकार प्रारूप स्ट्रिंग से मेल खाते हैं। यह वैरैडिक टेम्पलेट्स का उपयोग नहीं करता है, हालांकि, इसके बजाय खिलाए गए पैरामीटर (ऑपरेटर% के माध्यम से) एक-एक-एक का उपभोग करता है।

1

रिकॉर्ड के लिए, मैंने सी ++ 11 वैरिएडिक टेम्पलेट्स को पूरी तरह से हटा दिया, और पारंपरिक va_list का उपयोग कर समाप्त कर दिया।

__attribute__((format(printf, 2, 3))) 
void Frontend::log(const char *fmt, ...) { 
    va_list ap; 
    va_start(ap, fmt); 
    backend->true_log(fmt, ap); 
    va_end(ap); 
} 

void Backend::true_log(const char *fmt, va_list ap) { 
    // log the message somehow 
} 
संबंधित मुद्दे