2012-12-30 36 views
12

typeid(T).name() इस प्रकार के मानव समझने योग्य नाम को वापस नहीं लौटाता है, अगर हम कुछ वर्ग में टेम्पलेट तर्कों का नाम प्रिंट करना चाहते हैं तो इससे हमें बहुत मदद नहीं मिलती टेम्पलेट, खासकर जब हम डिबगिंग कर रहे हैं। हम अक्सर डिबगिंग में इस लेखन की तरह महसूस:अपने प्रिंट टेम्पलेट तर्कों के साथ सुंदर प्रिंट प्रकार और क्लास टेम्पलेट

print<Args...>(cout); //dump the names of all types to stdout! 

तो मैं बहुत प्रिंट उपयोगिता जो मुझे वर्ग टेम्पलेट का नाम देता है लिख रहा हूँ। मैं जो मुझे देता है "Y" जब मैं टेम्पलेट तर्क के रूप में इसे करने के लिए Y<int> पारित template_name नामक एक वर्ग टेम्पलेट का उपयोग कर रहा

print<int>(cout);    //prints int 
print<int, double, char>(cout); //prints int, double, char 
print<std::string>(cout);  //prints std::basic_string<char, .. etc> 
print<std::wstring>(cout);  //prints std::basic_string<wchar_t, .. etc> 
print<X<int,Y<int>>>(cout);  //prints X<int, Y<int>> 

आंतरिक रूप से,: ठीक है, यह आसान कुछ नमूना उपयोग के माध्यम से इसे समझने की है। यहां बताया गया है कि यह प्रत्येक उपयोगकर्ता श्रेणी टेम्पलेट के लिए आंशिक रूप से विशिष्ट कैसे है।

#define DEFINE_TEMPLATE_NAME(template_type) \ 
template<typename ... Ts>\ 
struct template_name<template_type<Ts...>>\ 
{\ 
    static const char* name()\ 
    {\ 
     return #template_type;\ 
    }\ 
}; 

और उपयोगकर्ता अपने टेम्पलेट वर्ग रजिस्टर करने के लिए इस मैक्रो का उपयोग करने की आवश्यकता है के रूप में:

DEFINE_TEMPLATE_NAME(std::basic_string); 
DEFINE_TEMPLATE_NAME(std::vector); 
DEFINE_TEMPLATE_NAME(X); //X is a class template 
DEFINE_TEMPLATE_NAME(Y); //Y is a class template 

काम करता है ऐसा इसलिए है क्योंकि विशेषज्ञता template_name<template_type<Ts...>>प्रकार केवल पर एक variadic वर्ग टेम्पलेट है, जो इसका मतलब है है तक सभी टेम्पलेट पैरामीटर प्रकार के रूप में मुझे क्लास टेम्पलेट का नाम वापस कर देगा। यह भी रूप में अच्छी तरह समारोह-प्रकार और सदस्य-समारोह-प्रकार के मुद्रित करने में सक्षम है:

typedef void fun(int,int); 

//lets use snl::name() which returns name instead of printing! 
std::cout << snl::name<fun>(); //prints : void(int,int) 
std::cout << snl::name<fun*>(); //prints : void(*)(int,int) 

कृपया अन्य मिनट विवरण के साथ the working code here देखते हैं। यह अब तक बहुत अच्छा काम करता है।

लेकिन अब मैं इस पर सुधार लाने कर रहा हूँ, और गैर प्रकार के तर्क Tempate के लिए समर्थन जोड़ने के लिए चाहते हैं और मिश्रित टेम्पलेट तर्क के रूप में अच्छी तरह से:

template<int...> 
struct Z{}; 

//non-type template arguments : 1,2,3 
snd::print<Z<1,2,3>>(cout); //should print Z<1,2,3> 

//mixed template arguments : int, 100 
snd::print<std::array<int,100>>(cout); //should print std::array<int,100> 

मैं ऐसा कैसे होगा? मैं इस तरह के वर्ग टेम्पलेट और इसके तर्कों का नाम सामान्य रूप से कैसे प्राप्त करूं?

+5

जीसीसी में एक demangler है जो बहुत उपयोगी टेम्पलेट वर्ग नाम प्रिंट करता है ... –

+0

@KerrekSB: हाँ, लेकिन यह मानक नहीं है। मुझे ऐसा कुछ चाहिए जो हर जगह काम करता हो। – Nawaz

उत्तर

6

मुझे खेद है कि यह एक "नकारात्मक उत्तर" है (मैं आपका प्रश्न उठा रहा हूं), लेकिन मुझे डर है कि आप ऐसा नहीं कर सकते हैं। यहां तक ​​कि केवल टेम्पलेट वर्ग है जो गैर प्रकार पैरामीटर के सजातीय सूची (template<int, int> जैसे, template<char, char, char>, आदि) को स्वीकार करने पर विचार, तो आप इस तरह के एक विशेषज्ञता की आवश्यकता होगी:

template<typename T> 
struct single_type 
{ 
    // ... 
}; 

template<typename U, template<U...> class C, U... Us> 
struct single_type<C<Us...>> 
{ 
    // ... 
}; 

इस विशेषज्ञता, कानूनी लेकिन बेकार है क्योंकि तर्क प्रकार U कभी नहीं लिया जा सकता है। आप सबसे आम प्रकारों (int..., char... इत्यादि) के अक्षरों की वर्दी सूचियों के लिए समर्पित विशेषज्ञता परिभाषित कर सकते हैं, लेकिन मिश्रित तर्कों के अकेले अनुक्रमों को अकेले ही अलग-अलग प्रकार के अनुक्रमों को कवर करना असंभव होगा।

मुझे डर है कि हमें जो कुछ भी आप ढूंढ रहे हैं उसे प्राप्त करने के लिए हमें प्रतिबिंब का समर्थन करने के लिए सी ++ का इंतजार करना होगा।

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

  • कोई संबंधित समस्या नहीं^_^