2014-09-10 2 views
14

मैं यह जांचना चाहता हूं कि एक गैर-सदस्य फ़ंक्शन जो टी पैरामीटर प्रकार स्वीकार करता है या नहीं। ऐसा करने के लिए मैंने void_t सीपीपीकॉन पर श्री वाल्टर ई ब्राउन द्वारा प्रस्तुत "चाल" का उपयोग किया (एक ही चाल बिना किसी समस्या के काम करता है यह जांचने के लिए कि कोई सदस्य प्रकार या सदस्य फ़ंक्शन मौजूद है)।जांच कर रहा है कि गैर-सदस्य फ़ंक्शन जो टी पैरा स्वीकार करता है

#include <iostream> 
#include <type_traits> 

template<typename...> 
using void_t = void; 

void Serialize(float&) 
{ 
} 

template<typename T, typename = void> 
struct has_external_serialize : std::false_type 
{ 
}; 

template<typename T> 
struct has_external_serialize<T, void_t<decltype(Serialize(std::declval<T&>()))>> : std::true_type 
{ 
}; 

void Serialize(int&) 
{ 
} 

int main(int argc, const char * argv[]) 
{ 
    std::cout<<has_external_serialize<float>::value<<has_external_serialize<int>::value; 
} 

इस कोड को प्रिंट 11 जब जब बजना (xcode 5.1.1) के साथ संकलित जीसीसी और 10 का उपयोग कर संकलित।

मेरे प्रश्न है - क्या यह कोड सही है? यदि हां, क्या क्लैंग या जीसीसी में एक बग में कोई बग है या कोड कुछ "कार्यान्वयन परिभाषित" क्षेत्र में है और मुझे लगता है कि यह सभी प्लेटफॉर्म पर समान व्यवहार नहीं करेगा?

+0

अपनी विशेषज्ञता से पहले निर्भर प्रकार, और 'std' प्रकार चिपकाएं। अन्य प्रकार एडीएल का उपयोग करें। तब clang खुश हो जाएगा।मेरा मानना ​​है कि आपने जो किया वह बीमार है, लेकिन इसे साबित करने के लिए समय नहीं है – Yakk

+3

जीसीसी (कम से कम 4.9.0) में एक बग की तरह लगता है, क्योंकि यह '11' प्रिंट करता है, 'struct_external_serialize ())) >> std :: true_type' –

+1

@ फ़ेलिक्स: CppCon में आपका स्वागत है! :-) –

उत्तर

4

compilers के बीच विसंगति void_t की परिभाषा के कारण होता है: Is there a compiler bug exposed by my implementation of an is_complete type trait? संक्षेप में, मानक स्पष्ट नहीं था उर्फ ​​टेम्पलेट विशेषज्ञताओं में अप्रयुक्त तर्क प्रतिस्थापन विफलता में परिणाम सकता है या बस अनदेखी कर रहे हैं या नहीं। CWG issue 1558 पर संकल्प स्पष्ट करता है कि प्रश्न में void_t की छोटी परिभाषा काम करनी चाहिए।

कि इस मुद्दे के साथ

template<typename... Ts> 
struct make_void { typedef void type;}; 

template<typename... Ts> 
using void_t = typename make_void<Ts...>::type; 

both compilers produce 10 का उपयोग कर के आसपास काम किया।

§14.6.4.2 [temp.dep.candidate]:

एक समारोह कॉल कि टेम्पलेट पैरामीटर पर निर्भर करता है के लिए, उम्मीदवार कार्यों में हमेशा की तरह देखने नियम (3.4.1 का उपयोग कर, पाए जाते हैं 3.4.2, 3.4.3) सिवाय इसके कि:

  • देखने अयोग्य नाम लुकअप (3.4.1) या योग्य नाम लुकअप (3.4.3) का उपयोग कर के भाग के लिए, टेम्पलेट परिभाषा से केवल समारोह घोषणाओं संदर्भ पाए जाते हैं।
  • संबंधित नेमस्पेस (3.4.2) का उपयोग करके लुकअप के हिस्से के लिए, केवल टेम्पलेट परिभाषा संदर्भ या टेम्पलेट तत्काल संदर्भ में पाए गए फ़ंक्शन घोषणाएं पाई जाती हैं।

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

Serialize के लिए अयोग्य देखने टेम्पलेट परिभाषा संदर्भ में किया जाता है और Serialize(int &) नहीं मिलेगा, और वहाँ प्रकार int& का एक तर्क के लिए कोई ADL है, तो 10 सही उत्पादन होता है।

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