पर एक लिंक है यह इस बात पर निर्भर करता है कि आप इनका उपयोग कैसे करते हैं निरंतर अभिव्यक्तियां
ओडीआर (एक परिभाषा नियम) कहा गया है कि
(§3.2/2) [...] एक चर जिसका नाम एक संभावित मूल्यांकन अभिव्यक्ति के रूप में प्रकट होता है ओडीआर से इस्तेमाल किया है, जब तक यह एक है ऑब्जेक्ट जो निरंतर अभिव्यक्ति (5.1 9) में दिखाई देने के लिए आवश्यकताओं को पूरा करता है और lvalue-to-rvalue रूपांतरण (4.1) तुरंत लागू होता है। [...]
(और फिर, विशेष नियम, अपवाद और अपवादों की अपवाद के बहुत सारे पालन करें।)
किसी भी चर है कि ओडीआर से इस्तेमाल किया, ठीक एक परिभाषा होनी चाहिए। आपके निरंतर अभिव्यक्तियों में एक घोषणा है, लेकिन परिभाषा नहीं है, इसलिए यह तब तक ठीक हो जाता है जब तक कि आप उनमें से एक का उपयोग न करें।
उदाहरण के लिए, निम्नलिखित में अच्छी तरह से चला जाता है:
int main() {
E e = GetE<float>::type;
return 0;
}
लेकिन यह नहीं करता है:
क्योंकि
void f(const E &)
{ }
int main() {
f(GetE<float>::type);
return 0;
}
f
एक (स्थिरांक) संदर्भ की आवश्यकता है, इसलिए lvalue करने वाली rvalue रूपांतरण नहीं किया जा सकता तुरंत लागू, इसलिए यह एक odr-use का गठन करता है। संकलक शिकायत करेगा कि यह एक परिभाषा याद करता है।
(टिप्पणी। शाफिक यघमोर को मिली (टिप्पणियां देखें), यदि संकलक ऑप्टिमाइज़ेशन का उपयोग करता है तो आपको कोई शिकायत नहीं मिल सकती है, क्योंकि संदर्भों को अनुकूलित किया जा सकता है। कंपाइलर शिकायत को पुन: उत्पन्न करने के लिए, -O0
ध्वज (या इसी तरह के, कंपाइलर के आधार पर)।
समस्या को हल करने के लिए, आवश्यक परिभाषा सामान्य तरीके से प्रदान की जा सकती है, यानीstruct परिभाषा के बाहर:
constexpr E GetE<float>::type;
constexpr E GetE<char>::type;
constexpr E GetE<int>::type;
लेकिन इस के बाद से सीपीपी (नहीं हेडर फाइल), तो आपको दो अलग अलग स्थानों में घोषणाओं और परिभाषाओं बनाए रखने के लिए है, जो होने पहुंच जाएंगे में होती हैं करने के लिए होगा बोझिल।
समाधान तुम सिर्फ अपनी टिप्पणी में सुझाव दिया है, यानि कि एक constexpr (और इनलाइन) समारोह को परिभाषित, सही लगता है:
template <class T> constexpr E GetE();
template <> constexpr E GetE<float>()
{ return TYPE_FLOAT; }
template <> constexpr E GetE<char>()
{ return TYPE_CHAR; }
template <> constexpr E GetE<int>()
{ return TYPE_INT; }
void f(const E &)
{ }
int main() {
E e = GetE<float>();
f(GetE<float>());
return 0;
}
हाँ यह उचित लगता है। मैं 'tmpl ई गेटई()' जैसे फ़ंक्शन टेम्पलेट का उपयोग करने के लिए बदल गया हूं और फिर इसके बजाय विशेषज्ञता और इसे ठीक कर दिया है। धन्यवाद। –
@jogojapan मैं आपकी टिप्पणी से सीखने की कोशिश कर रहा हूं लेकिन मुझे कोड के अंतिम भाग का उपयोग करके कोई त्रुटि नहीं दिखाई दे रही है: http://liveworkspace.org/code/4oTEis मुझे क्या याद आ रही है? धन्यवाद –
@ShafikYaghmour यह '-O2' कंपाइलर ध्वज की वजह से है। यह संदर्भों को दूर करता है। अच्छी टिप्पणी, हालांकि, मैं इसका उत्तर में उल्लेख करूँगा। – jogojapan