VS2015

2015-10-17 9 views
12

में टेम्पलेट प्रकार उपनाम के साथ अप्रत्याशित व्यवहार निम्नलिखित कोड VS15 समुदाय के साथ संकलित करता है और "हैलो" प्रिंट करता है।VS2015

#include <functional> 
#include <iostream> 

template<typename T> 
using void_template_alias_t = void; 

template<typename T> 
using Func = std::function<void(T)>; 

template<typename T> 
using FuncVoid = Func<void_template_alias_t<T>>; 

int main() 
{ 
    FuncVoid<void> hello = [] { std::cout << "Hello\n"; }; 
    hello(); 
} 

मुझे लगता है कि इसे संकलित करने की अनुमति नहीं है।

मैं चारों ओर खेल रहा था, कोड थोड़ा और जटिल था। मुझे यह काम करने की उम्मीद है, लेकिन अचानक एहसास हुआ कि इस कोड को संकलित नहीं करना चाहिए क्योंकि आप Func<void> नहीं कर सकते (या क्या मैं इसके साथ गलत हूं?)।

  • क्या मुझे जादू का कामकाज मिला?
  • क्या यह सी ++ 14 मानक से एक नया व्यवहार है?
  • या यह बस एक कंपाइलर बग है?

संपादित करें: निम्न और अधिक सरलीकृत संस्करण संकलित नहीं करता है।

#include <functional> 
#include <iostream> 

template<typename T> 
using Func = std::function<void(T)>; 

int main() 
{ 
    Func<void> hello = [] { std::cout << "Hello\n"; }; 
    hello(); 
} 
  • तो क्यों संकलन और मैं के रूप में काम उपरोक्त कोड पहले की उम्मीद है?
  • क्या यह सही कार्यान्वयन है, यदि नहीं, तो यह कैसा दिखता है?
+0

'foo (शून्य)' और 'एक्स = शून्य का उपयोग करके' अंतर की दुनिया है; foo (एक्स), '। मुझे आश्चर्य होगा अगर अन्य कंपाइलर्स ने इसे स्वीकार किया। –

+0

ओह, मुझे भी यकीन था। मानक कहता है कि "पैरामीटर सूची' (शून्य) 'खाली पैरामीटर सूची के बराबर है।", लेकिन यह निर्दिष्ट नहीं करता है कि '(शून्य)' शाब्दिक पाठ है। और इसके लिए कोई विशेष व्याकरण उत्पादन नहीं है, और दोनों जी ++ और विजुअल सी ++ संकलन 'शून्य फू (एक्स)' जहां 'एक्स' 'शून्य' के लिए एक नाम है, और वे कॉल 'foo()' संकलित करते हैं। –

+0

शायद मैं स्पष्ट रूप से बेहतर ध्यान दूंगा, कि व्याख्या जहां '(शून्य)' एक ऐसे फ़ंक्शन को संदर्भित करती है जहां एकल तर्क का * प्रकार * प्रभावी रूप से 'शून्य' होता है, और उसके बाद किसी भी तर्क के साथ फ़ंक्शन को इंगित करता है, काम नहीं करता है टेम्पलेट कोड के साथ अच्छी तरह से एक तर्क के साथ समारोह को आमंत्रित करता है, यानी यह अव्यवहारिक है। फिर भी एमएसवीसी और मिनजीडब्ल्यू जी ++ दोनों गैर-टेम्पलेट 'foo (My_void)' स्वीकार करते हैं और 'foo() 'को कॉल करते हैं। :( –

उत्तर

5

या यह बस एक कंपाइलर बग है?

वह। @TC से उल्लेख किया है, CWG #577 प्रासंगिक है:

[...] वहाँ था कुछ समारोह टेम्पलेट्स वर्ग टेम्पलेट्स के और सदस्य कार्यों के उपचार से अधिक व्यक्त चिंता का विषय है, तो सी ++ नियम बदल गया: टेम्पलेट पैरामीटर के लिए T, T प्रकार का एक पैरामीटर लेता है, यदि कोई T = void के साथ तत्काल किया गया था तो कोई पैरामीटर फ़ंक्शन बन जाएगा?

यह एक उचित शिकायत है, लेकिन आप के लिए दुर्भाग्यपूर्ण, सदस्य कार्य/सदस्य समारोह टेम्पलेट्स और प्रकार आईडी रों संकल्प द्वारा समान रूप से प्रभावित हुए:

एक पैरामीटर सूची एक से मिलकर का एकल नामित पैरामीटर गैर-निर्भर प्रकार void खाली पैरामीटर सूची के बराबर है।

इस प्रकार आपके स्निपेट बीमार हैं, क्योंकि पैरामीटर का प्रकार वास्तव में निर्भर है।


यह एक सही कार्यान्वयन है यदि नहीं, तो यह कैसे की तरह लग रहे हैं?

कोई सही कार्यान्वयन नहीं है।यदि आपको खाली पैरामीटर सूची के साथ फ़ंक्शन प्रकार की आवश्यकता है, तो आपको टेम्पलेट पैरामीटर से स्वतंत्र निर्दिष्ट करना होगा।

तो संकलन और काम करने के ऊपर कोड क्यों पहले की उम्मीद है?

मेरे सर्वोत्तम अनुमान: "-> खाली सूची परिवर्तन void" कुलपति ++ आश्वस्त है कि पैरामीटर प्रकार नहीं है एक निर्भर प्रकार "सीवी void", लेकिन करने से पहले void_template_alias_t<T>के बाद का प्रतिस्थापन है। हालांकि, यह समझना अक्सर मुश्किल होता है कि कैसे VC++ (या उस मामले के लिए कोई संकलक) आंतरिक रूप से सोचता है।

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