2013-05-01 5 views
6

सी ++ में मेटाप्रोग्रामिंग के कई उदाहरण देखने के बाद जो कक्षाओं के गुणों (जैसे knowing if a type is a specialization of a template) की पहचान कर सकते हैं, या यह जानकर कि कक्षा में दिए गए नेस्टेड प्रकार को शामिल किया गया हो; लेकिन मैं सोच रहा था कि परीक्षण या विशेषता लिखना संभव था जो पिछले एक के विपरीत को निर्धारित करता है - यह जांचने के लिए कि Typeclass या struct के भीतर घोंसला है या नहीं।सी ++ - पता है कि एक प्रकार/वर्ग घोंसला है या नहीं?

दूसरे शब्दों में, मैं निम्नलिखित स्यूडोकोड के बराबर की तलाश में हूँ:

template <typename Type> struct is_nested { 
    enum { value = {__some magic__} }; 
}; 

typedef int type1; 
struct Something { typedef int internal_type; }; 
typedef Something::internal_type type2; 

//...later, likely at a different scope 

is_nested<int>::value; // yields false 
is_nested< std::vector<int>::iterator >::value; // yields true 
is_nested<type1>::value; // yields false 
is_nested<type2>::value; // yields true 

मैं जानता हूँ कि मैं sizeof का उपयोग हां/नहीं परीक्षण लागू करने के लिए कर सकते हैं और मुझे लगता है Type उन परीक्षण का हिस्सा है, लेकिन मैं यह नहीं समझ सकता कि परीक्षण में किसी भी प्रकार के "किसी भी व्यवहार्य प्रकार" को कैसे प्लग करें ताकि मैं Anytype::Type जैसी अभिव्यक्ति बना सकूं।

 
template 
struct is_nested 
{ 
    typedef char yes; 
    typedef struct { char u[2]; } no; 

    // Herein lies the problem 
    ???? static yes test(char [ sizeof(Anytype::Type) ]) ; 
    ???? static no test(...); 


public: 
    enum { value = sizeof(test(0)) == sizeof(char) }; 
}; 

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

मैं एक सी के लिए देख रहा हूँ ++ समाधान उस में हो सी ++ 11 या सी ++ 03 है, लेकिन पहले मामले में मैं इसे और अधिक अगर यह स्वागत करेंगे backportable था। और टेम्पलेट्स प्रकार, नहीं नाम के साथ काम करते हैं -

+1

समस्या का समाधान करने के लिए क्या समस्या है? –

+0

मैं ज्यादातर 'एन ++ में टाइपएफ़ एनम्स का अनुकूलन] [http://stackoverflow.com/a/11856721/399580) को सुधारने के तरीके पर सिद्धांत कर रहा हूं,' एनम 'के लिए रिलेशनल ऑपरेटरों को अक्षम करके जो अंदर घोंसला है structs; यह उस समस्या से निपटने के लिए अध्ययन कर रहे दो दृष्टिकोणों में से एक है। –

उत्तर

1

आप क्या कह रहे हैं नहीं बल्कि इसलिए कि आप हमेशा नहीं बता सकता कि एक प्रकार का नाम एक नेस्टेड प्रकार को दिखाता है या नहीं, एक तकनीकी सीमा के कारण संभव है, लेकिन नहीं।

इस मामले में, उदाहरण के लिए:

is_nested< std::vector<int>::iterator >::value 

आप नहीं जानते कि क्या iterator है।

template<typename T> 
struct my_vector 
{ 
    typedef T* iterator; 
    // ... 
}; 

क्या करना चाहिए is_nested<my_vector<int>::iterator>::value उपज: इस वर्ग के my_vector पर विचार करें? आप शायद परिणाम true होने की उम्मीद करते हैं।

हालांकि, यहां घोंसला क्या है ऊर्फ, प्रकार स्वयं नहीं: प्रकार int* घोंसला नहीं है। वास्तव में, मैं आप निम्नलिखित false उपज करना चाहते हैं की उम्मीद:

is_nested<int*>::value 

तो यहाँ एक ही is_nested<T> विशेषता उपज चाहिए दो अलग परिणाम एक ही प्रकार T (int*, इस मामले में) दिया। is_nested<> पर आधारित जानकारी value को T प्रकार से पुनर्प्राप्त नहीं किया जा सकता है - और टेम्पलेट्स प्रकारों के साथ काम नहीं करते हैं, नाम नहीं।

+0

पॉइंटर-ए-इटरेटर और अन्य समान स्थितियों के मामले पर उत्कृष्ट बिंदु उत्पन्न हो सकता है। उस बिंदु पर हालांकि मैं उम्मीद करता हूं कि संकलक इसे हल करने में सक्षम होगा क्योंकि iterator _type_ ज्ञात है; इस तरह के मामले में, यह विशेषता उदाहरण के लिए निर्धारित करेगी कि एक कंटेनर प्रकार में संगत भंडारण है (यदि निश्चित रूप से इटरेटर प्रकार कच्चा सूचक होता है, और _likely_ उपज 'सत्य' अन्यथा होता है तो निश्चित रूप से 'झूठी' उत्पन्न करेगा)। –

+0

@LuisMachuca: जब आप "हल करने के लिए * यह *" कहें तो आपका क्या मतलब है यह सुनिश्चित नहीं है। "यह" से आपका क्या मतलब है? आपकी 'is_nested <>' विशेषता इनपुट में * प्रकार * प्राप्त होगी, जो दोनों मामलों में 'int *' है। यह सब कुछ है 'is_nested <> 'जानता है। समान टेम्पलेट तर्क दिए गए विभिन्न परिणामों का उत्पादन करने के लिए कोई तरीका नहीं है कि आप 'is_nested <>' प्रोग्राम कर सकते हैं। –

+0

... सच है, दुर्भाग्य से। इसका मतलब है कि मुझे इस दृष्टिकोण को त्यागना होगा। –

0

यह जांचना संभव हो सकता है कि "कैनोलिक प्रकार" (सभी उपनामों के बाद परिणाम प्रकार हल हो गया है) को कंपाइलर की गैर-मानक सुविधाओं का उपयोग करके घोंसला दिया जाता है।

CTTI संकलन समय पर एक प्रकार का नाम प्राप्त कर सकते हैं।फिर स्ट्रिंग में : लगता है:

#include <vector> 
#include "ctti/type_id.hpp" 

constexpr bool has_colon(const ctti::detail::string& s, size_t i) { 
    return i < s.length() ? (s[i] == ':' || has_colon(s, i + 1)) : false; 
} 

template<typename T> 
using is_nested = integral_constant<bool, has_colon(ctti::type_id<T>().name(), 0)>; 

typedef int type1; 
struct Something { typedef int internal_type; }; 
typedef Something::internal_type type2; 

static_assert(!is_nested<int>::value, ""); 
static_assert(is_nested< std::vector<int>::iterator >::value, ""); 
static_assert(!is_nested<type1>::value, ""); 
// static_assert(is_nested<type2>::value, ""); // fail 

4 की जांच विफल हो जाएगा क्योंकि type2 सिर्फ int है, जो नहीं लगाए गए है।

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