2015-11-18 3 views
10

मैं किसी भी तरह से छिपाने वाले std::string::operator=(char) ओवरलोड को बहिष्कृत करने के रूप में किसी भी तरह से अक्षम/चिह्नित करने की कोशिश कर रहा हूं (जो मेरे अनुभव में केवल तभी प्रयोग किया जाता है जब गलती से एक स्ट्रिंग को पूर्णांक आवंटित किया जाता है, और सूक्ष्म और बग को ट्रैक करना मुश्किल होता है)। यह* मेरी लाइब्रेरी में * मानक लाइब्रेरी * फ़ंक्शन/विधि को बहिष्कृत (या पूरी तरह अक्षम) के रूप में कैसे चिह्नित करें?

#include <string> 
#include <type_traits> 

template<> std::basic_string<char> &std::basic_string<char>::operator=(char c) { 
    static_assert(false, "Don't use this!"); 
} 

जो विफल रहता है <string> के रूप में पहले से ही std::string

  • [[deprecated]] विशेषता का एक स्पष्ट इन्स्टेन्शियशन करता है में एक स्थिर ज़ोर साथ

    • एक स्पष्ट विशेषज्ञता,:

      मैं के साथ की कोशिश की विभिन्न पदों में ऊपर की तरह एक समान घोषणा पर लागू; मैंने कोशिश की कोई भी स्थिति किसी भी उचित परिणाम देने के लिए लग रहा था;

    • =delete, जो ऊपर के समान कारणों से विफल रहता है;
    • मैंने लिंकर ट्रिक्स का उपयोग करने के बारे में सोचा (इसी तरह के एक ही प्रोजेक्ट में, --wrapld लिंकर विकल्प का उपयोग करके उपयोग पर रनटाइम चेक है), लेकिन तथ्य यह है कि यह एक टेम्पलेट और इनलाइन विधि इस मामले को जटिल करता है।

    अब सवाल:

    • वहाँ किसी भी तरह निष्क्रिय करने के लिए (=delete साथ क्या होगा के रूप में) मानक पुस्तकालय में किसी भी समारोह या विधि एक मानक पद्धति है (पढ़ें: एक पुस्तकालय में आप जहां परिवर्तन नहीं कर सकते हेडर में घोषणाएं)?
    • उपरोक्त के रूप में, लेकिन, अक्षम होने की बजाय, एक चेतावनी जोड़ें (जैसा कि [[deprecated]] के साथ होगा);
    • मानक विधि में विफल, क्या कुछ g ++ - विशिष्ट है?
    • यदि कोई "सामान्य" (= किसी भी विधि, किसी भी वर्ग, किसी भी फ़ंक्शन, ...) समाधान पर लागू होता है, तो क्या ऐसा कुछ है जिसे हम इस विशिष्ट मामले पर लागू कर सकते हैं (= टेम्पलेट वर्ग की विधि को अक्षम करें, संभवतः यहां तक ​​कि सिर्फ एक विशिष्ट तात्कालिकता)?

      $ g++ -O0 test.cpp -Wl,--wrap=_ZNSsaSEc 
      

      स्पष्टीकरण::

      _ZNSsaSEc अपने हमलावर समारोह का सजाया नाम है:

      $ echo _ZNSsaSEc | c++filt 
      std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator=(char) 
      

  • +1

    यदि आप एक स्थैतिक जोर या हटाए गए फ़ंक्शन का उपयोग करने का प्रयास कर रहे हैं तो आपके पास "बहिष्कृत" की एक मजेदार परिभाषा है। –

    +0

    @ जोनाथन वाक्ली: "पूरी तरह से बहिष्कृत या अक्षम"; लेकिन जहां तक ​​मेरा संबंध है, यह अनिवार्य रूप से वही है, मैं शायद इस तरह की चेतावनी पर 'वायुयान' का उपयोग करूंगा, वैसे भी उस असाइनमेंट ऑपरेटर का उपयोग करने का कोई वैध कारण नहीं है (ठीक है क्योंकि इसका उपयोग करने का कोई कारण नहीं है, कहता है, 'मिलता है 'या स्ट्रिंग अक्षर = =' char * 'रूपांतरण विरासत कोड संगतता के अलावा)। –

    उत्तर

    4

    आप निम्न संकलक/लिंकर विकल्प का उपयोग कर सकते हैं -Wl कंपाइलर विकल्प लिंकर को विकल्प पास करना है।

    और --wrap=<symbol> लिंकर विकल्प वैकल्पिक __wrap_<symbol> पर दिए गए प्रतीक के किसी भी संदर्भ को बदल देता है।

    test.cpp:(.text+0x26): undefined reference to `__wrap__ZNSsaSEc' 
    

    और -O0 अनुकूलन अक्षम करें और समारोह इनलाइन करने से संकलक रोकने के लिए है: और के बाद से आप कर रहे हैं (उम्मीद) नहीं एक समारोह __wrap__ZNSsaSEc नामित परिभाषित, आप एक अच्छे लिंकर त्रुटि मिल जाएगा।अगर सर्कलबेलस्टा ने टिप्पणी में बताया तो लिंकर चाल काम नहीं करेगी।

    शायद एक हैक का थोड़ा सा, लेकिन हे, यह काम करता है!

    +1

    @ सेर्जबलेस्टा: ठीक है, '-ओ0' के साथ, यह काम करता है। '-O1' या उच्चतर के साथ यह नहीं है। – rodrigo

    +0

    ऐसा मत करो! यह बिल्कुल अनजान है कि यह त्रुटि गलत तरीके से प्रयुक्त असाइनमेंट ऑपरेटर की वजह से है। सड़क के नीचे कुछ साल इस लिंकर ध्वज हार्ड-टू-ट्रैक बग हो सकता है। – Richard

    1

    अच्छा, मुझे डर है कि मानक पुस्तकालय का उद्देश्य है ... मानक, और इस तरह डेवलपर्स को इसे ट्विक करने की अनुमति देने के लिए हुक प्रदान नहीं करते हैं।

    एक बदसूरत तरह से (कभी नहीं कहते हैं कि मैं तुम्हें ;-) इसका इस्तेमाल करते हैं सलाह देने के), तथ्य यह है उपयोग करने के लिए मानक पुस्तकालय हेडर सिर्फ पाठ कर रहे हैं कि फ़ाइलों होगा ताकि आप आसानी से उन्हें आप स्थानीय developpement वातावरण में बदल सकते हैं। संभवतः कम खराब तरीका, संशोधित शीर्षलेख को छोड़कर मूल शीर्षलेखों के लिंक वाले फ़ोल्डर को सेट करना होगा और सिस्टम हेडर के लिए उस फ़ोल्डर का उपयोग करने के लिए संकलक को निर्देश देना होगा।

    इस तरह, आप कुछ भी आप चाहते हैं बदल सकते हैं, लेकिन ... पोर्टेबिलिटी और रख-रखाव की ... यह वास्तव में एक डेस्पराडो समाधान है ...

    +0

    पहला वाक्य एक महत्वपूर्ण बिंदु का थोड़ा सा है; अपनी पसंद की गतिशील भाषा लें (जावास्क्रिप्ट, पायथन, रूबी, ...), वहाँ * एक मानक पुस्तकालय है, लेकिन आप इसे सबसे विचित्र तरीकों से मोड़ सकते हैं; भी, सी ++ मानक पुस्तकालय अनुकूलन बिंदु (टेम्पलेट तर्क के रूप में, या "खुले कार्यों" के रूप में, 'std :: हैश' के रूप में) के रूप में प्रदान करता है, POSIX और Win32 मैक्रोज़ के माध्यम से सामान के सशर्त समावेशन की अनुमति देता है, साथ ही सी ++ के सभी ठोस कार्यान्वयन झंडे या मानक पुस्तकालय के लिए अनुकूलन, और यहां तक ​​कि भाषा के लिए भी (संकलन के लिए संकलन-समय स्विच के रूप में, मैक्रोज़ को परिभाषित करने के लिए, ...)। –

    0

    यह बजना ++ विशिष्ट है, क्योंकि मैं नहीं जानता कि क्या समकक्ष कार्यक्षमता gnu टूलचेन में बुलाया जाता है। यह कुछ हद तक अधिक है।

    रॉड्रिगो के प्रतीक को स्वैप करने के लिए लिंकर का उपयोग करने का सुझाव गैर-रेखांकित मामलों के लिए बहुत अच्छा है। यदि आप कभी-कभी O0 पर सब कुछ बनाते हैं तो पर्याप्त होगा।

    अन्यथा, llvm (clang) टूलचेन अनुकूलन पाइपलाइन पर नियंत्रण की आश्चर्यजनक मात्रा प्रदान करता है। उदाहरण के लिए, आप ऑप्टिमाइज़ेशन के बिना संकलित कर सकते हैं, फिर ऑप्टिमाइज़ेशन को ऑप्ट का उपयोग करके चलाएं, फिर किसी ऑब्जेक्ट फ़ाइल में कनवर्ट करें।

    clang++ -c test.cpp -O0 --emit-llvm test.ll 
    opt -O3 test.bc -o faster.ll 
    clang++ -c faster.bc -o test.o 
    

    ऑप्ट टूल एक्स्टेंसिबल है। मैं ईमानदारी से नहीं कह सकता कि यह विस्तार करने के लिए तुच्छ है, लेकिन प्रक्रिया अच्छी तरह से प्रलेखित है। आप एक कंपाइलर पास लिख सकते हैं जो चेतावनी देता है कि आपका मानक लाइब्रेरी फ़ंक्शन कब देखा जाता है। अंतिम परिणाम की तरह कुछ लागू किया जा सकता है:

    clang++ -c test.cpp -O0 --emit-llvm test.ll 
    opt --load DeprecationPass.so test.bc -o /dev/null 
    opt -O3 test.bc -o faster.ll 
    clang++ -c faster.bc -o test.o 
    

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

    कुल मिलाकर, रॉड्रिगो के सुझाव के बाद और कभी-कभी ओ0 पर पूरे उत्पाद का निर्माण शायद एक बेहतर योजना है - लेकिन यह रोमांचक है कि क्लैंग आपको इस तरह की चीजें करने देता है।

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