मैं एक ही फ़ंक्शन के दो अलग-अलग संस्करण बनाने की कोशिश कर रहा हूं, जिनमें से केवल एक ही संकलित किया जाएगा। उदाहरण के तौर पे:

#[cfg(debug_assertions)]
fn do_something(x: usize) -> usize {
    x + 1
}

#[cfg(not(debug_assertions))]
fn do_something() -> usize {
    0
}

यह ठीक काम करता है और मैं do_something के सही संस्करण को भी कॉल कर सकता हूं अगर मुझे पता है कि मैं किसे कॉल कर रहा हूं (व्यवहार में, फ़ंक्शन ठीक वही काम करेंगे, डीबग वाला बस कुछ सत्यापन के लिए अधिक जानकारी की आवश्यकता है)। इसलिए मैं दो संगत main फ़ंक्शन बना सकता हूं:

#[cfg(debug_assertions)]
fn main() {
    do_something(0);
}

#[cfg(not(debug_assertions))]
fn main() {
    do_something();
}

लेकिन यह बहुत अनाड़ी है, और मैं कोड का केवल एक संस्करण रखना चाहता हूं जो debug_assertions पर निर्भर न हो। मैं कुछ ऐसा करना चाहता हूं:

macro_rules! call {
    ($func:ident, $optional_arg:expr) => {{
        if cfg!(debug_assertions) {
            $func($optional_arg);
        } else {
            $func();
        }
    }};
}

fn main() {
    call!(do_something, 0);
}

और फिर जहां भी मैं इस फ़ंक्शन को कॉल करता हूं, या इसी तरह के मैक्रो का पुन: उपयोग करें। लेकिन यह संकलित नहीं करता है:

  --> main.rs:16:13
   |
2  | fn do_something(x: usize) -> usize {
   | ---------------------------------- defined here
...
16 |             $func();
   |             ^^^^^-- supplied 0 arguments

   |             |
   |             expected 1 argument
...
22 |     call!(do_something, 0);
   |     ----------------------- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

मुझे समझ में नहीं आता कि मुझे त्रुटि क्यों मिलती है, क्योंकि गलत फ़ंक्शन कॉल को भी संकलित नहीं किया जाना चाहिए। फ़ंक्शन को एक ही हस्ताक्षर के लिए मजबूर करके और रिलीज़ संस्करण में अनावश्यक तर्क को अनदेखा करके त्रुटि को ठीक किया जा सकता है, लेकिन यह जाने का सही तरीका नहीं लगता है।

इस स्थिति में आप क्या करेंगे? मैक्रो उदाहरण संकलित क्यों नहीं करता है?

2
chuck 12 सितंबर 2020, 12:19

1 उत्तर

सबसे बढ़िया उत्तर

संदर्भ से:

cfg!, #[cfg] के विपरीत, कोई कोड नहीं हटाता है और केवल मूल्यांकन करता है सच या झूठ को। उदाहरण के लिए, if/else एक्सप्रेशन में सभी ब्लॉक blocks जब cfg! का उपयोग शर्त के लिए किया जाता है, तब वैध होने की आवश्यकता होती है, भले ही cfg! क्या मूल्यांकन कर रहा है

झंडे का मूल्यांकन संकलन समय में किया जाएगा लेकिन आप यह चेक रनटाइम पर कर रहे हैं। समस्या से बचने के लिए आपको विशेषताओं का उपयोग करने की आवश्यकता है:

macro_rules! call {
    ($func:ident, $optional_arg:expr) => {{
        #[cfg(debug_assertions)]
        $func($optional_arg);

        #[cfg(not(debug_assertions))]
        $func();
    }};
}
1
Ömer Erden 12 सितंबर 2020, 12:41