5

मैं एक टेम्पलेट फ़ंक्शन लिखना चाहता हूं जो केवल 2 संख्याओं (उदाहरण के लिए 3 और 5) के साथ काम करता है और यदि आप इसे किसी अन्य नंबर के साथ उपयोग करने का प्रयास करते हैं तो त्रुटि और त्रुटि देता है।इनट्स के साथ विशेषज्ञता के बारे में, और static_assert

मैं इस तरह से यह कर सकते हैं:

template<int x> 
void f(); 

template<> 
void f<3>() 
{ 
    cout << "f<3>()\n"; 
} 


template<> 
void f<5>() 
{ 
    cout << "f<5>()\n"; 
} 

और उसके बाद मैं इस समारोह सामान्य तरीके से कॉल कर सकते हैं:

f<3>(); 
f<5>(); 

और यह अच्छी तरह संकलित, और मैं अपने कार्य का उपयोग करने की कोशिश करता है, तो गलत:

f<10>(); 

संकलक मुझे एक त्रुटि देता है।

1.- इस मानक है:

मैं इस दृष्टिकोण के साथ 2 समस्या है? क्या मैं इंक के साथ एक टेम्पलेट विशेष कर सकता हूँ?

2.- यदि आप इस दृष्टिकोण का उपयोग करते हैं तो मुझे आपको जो त्रुटि मिलती है उसे पसंद नहीं है, क्योंकि त्रुटि उपयोगकर्ता को यह नहीं बताती कि उसने गलत तरीके से क्या किया है। मैं कुछ लिखना पसंद करूंगा जैसे:

template<int x> 
void f() 
{ 
    static_assert(false, "You are trying to use f with the wrong numbers"); 
} 

लेकिन यह संकलित नहीं करता है। ऐसा लगता है कि मेरा कंपाइलर (जीसीसी 5.4.0) पहले प्राथमिक टेम्पलेट को तुरंत चालू करने की कोशिश कर रहा है, और इसके कारण यह त्रुटि (static_assert का) देता है।

आपकी मदद के लिए धन्यवाद।

यदि आप सोच रहे हैं कि मैं ऐसा क्यों करना चाहता हूं क्योंकि मैं सीख रहा हूं कि माइक्रोकंट्रोलर प्रोग्राम कैसे करें। एक माइक्रोकंट्रोलर में आपके पास कुछ पिन होते हैं जो केवल कुछ चीजें करते हैं। उदाहरण के लिए, पिन 3 और 5 पिन होते हैं जिसमें आप स्क्वायर वेव उत्पन्न कर सकते हैं। एक आवेदन में मैं एक वर्ग तरंग उत्पन्न करने के लिए चाहते हैं, तो मैं इस तरह somthing लिखना चाहते हैं:

square_wave<3>(frecuency); 

लेकिन, कुछ महीने बाद मैं इस कोड का पुन: उपयोग (या इसे बदलने) एक differente माइक्रोकंट्रोलर के साथ एक और आवेदन में करना चाहते हैं, मैं चाहता हूं कि मेरा कंपाइलर मुझसे कहता है: "आह, इस माइक्रोकंट्रोलर में आप पिन 3 और 5 में स्क्वायर वेव उत्पन्न नहीं कर सकते हैं। इसके बजाय, पिन 7 और 9 का उपयोग करें"। और मुझे लगता है कि यह मुझे बहुत सारे सिरदर्द बचा सकता है (या शायद नहीं, मुझे वास्तव में पता नहीं है। मैं सिर्फ एक माइक्रोक्रोनरोलर प्रोग्राम करने का तरीका सीख रहा हूं)।

+0

"_but इस compile_ नहीं है" संकलन त्रुटि क्या है? किस परीक्षण के साथ? 'एफ <10>()' 'स्थिर जोर से संकलित नहीं होना चाहिए। – nefas

+0

@nefas यह 'x' के _any_ मान के साथ संकलित नहीं करता है। –

उत्तर

2

static_assert की स्थिति हमेशा false है, जो प्राथमिक टेम्पलेट को विनिर्देशों के चयन से पहले, ओवरलोड रिज़ॉल्यूशन में चयनित होने में विफल होने में विफल बनाता है। आप टेम्पलेट पैरामीटर x पर निर्भर करने के लिए static_assert की स्थिति बदल सकते हैं। .eg

template<int x> 
void f() 
{ 
    static_assert(x == 3 || x == 5, "You are trying to use f with the wrong numbers"); 
} 

LIVE

मानक से, $17.7/8,9 Name resolution [temp.res]:

तुरंत इसकी परिभाषा के बाद एक टेम्पलेट का एक काल्पनिक इन्स्टेन्शियशन एक निर्माण कि पर निर्भर नहीं करता की वजह से बीमार का गठन किया जाएगा एक टेम्पलेट पैरामीटर

...

अन्यथा, किसी टेम्पलेट के लिए कोई निदान जारी नहीं किया जाएगा जिसके लिए एक वैध विशेषज्ञता उत्पन्न की जा सकती है।

और $17.7.2/1 Dependent names [temp.dep]:

एक टेम्पलेट के अंदर, कुछ निर्माणों अर्थ विज्ञान जो एक इन्स्टेन्शियशन से दूसरे में अलग हो सकता है। ऐसा निर्माण टेम्पलेट पैरामीटर पर निर्भर करता है।

+0

अच्छा हाँ, लेकिन यह बहुत हैकी है। क्यों नहीं '= हटाएं;' इसके बजाय फ़ंक्शन? – Rakete1111

+0

@ Rakete1111 क्योंकि ओपी कुछ और स्पष्ट अनुकूलित संदेश चाहता है। – songyuanyao

+1

मुझे लगता है कि वे सिर्फ एक लिंकर के बजाय एक कंपाइलर त्रुटि चाहते हैं। लेकिन ठीक है :) – Rakete1111

5

1.- क्या यह मानक है? क्या मैं इंक के साथ एक टेम्पलेट विशेष कर सकता हूँ?

हां।

2.

template<int x> 
void f() 
{ 
    static_assert(false, "You are trying to use f with the wrong numbers"); 
} 

आप कुछ है कि टेम्पलेट पैरामीटर का मान पर निर्भर है में स्थिर ज़ोर हालत बदलने की जरूरत है।

template <int x> 
void f() 
{ 
    static_assert(x - x, "You are trying to use f with the wrong numbers"); 
} 

को काम करना चाहिए।


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

template <int I> 
void f(args...) { 
    do_f<I>{}(args...); 
} 
0

अन्य उत्तर केवल प्रस्ताव:

template <int I> 
struct do_f { 
    static_assert(I - I, "You are trying to use f with the wrong numbers"); 
}; 

template <> 
struct do_f<3> { 
    void operator()(args...) { ... } 
}; 

template <> 
struct do_f<5> { 
    void operator()(args...) { ... } 
}; 

तो फिर तुम एक आवरण समारोह जो समारोह वस्तु के लिए बाहर कॉल लिख सकते हैं: तो यह एक समारोह वस्तु के बजाय का उपयोग करने के सामान्य रूप में एक बेहतर विचार हो सकता है एक कामकाज विशेष रूप से क्योंकि इसमें कुछ बॉयलरप्लेट कोड लिखना शामिल है। ऐसा करने के लिए सबसे आसान काम

template<int x> 
void f() = delete; 

तो फिर तुम जैसे

error: call to deleted function 'f' 

एक अच्छा संकलक त्रुटि प्राप्त करेंगे जब आप एक गैर विशिष्ट int के लिए टेम्पलेट का दृष्टांत करने की कोशिश है।

#include <iostream> 

template<int x> 
void f() = delete; 

template<> 
void f<3>() 
{ 
    std::cout << "f<3>()\n"; 
} 

template<> 
void f<5>() 
{ 
    std::cout << "f<5>()\n"; 
} 

int main() 
{ 
    f<3>(); 
    f<5>(); 
    f<10>(); // BOOM! 
} 

Live example

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