2012-03-21 15 views
28

सी ++ में टेम्पलेट फ़ंक्शन बनाते समय टेम्पलेट के टाइपनाम को स्ट्रिंग के रूप में प्रदर्शित करने का एक आसान तरीका है? मैं मुझे क्या करना (कोड से पता चला संकलन नहीं है ध्यान दें) कोशिश कर रहा हूँ दिखाने के लिए एक साधारण परीक्षण मामला है:संकलन समय पर प्रिंट टेम्पलेट टाइपनाम

#include <stdio.h> 
template <typename type> 
type print(type *addr) 
{ 
    printf("type is: %s",typename); 
} 

int main() 
{ 
    int a; 
    print(&a); 
} 

// Would like to print something like: 
// type is: int 

मुझे लगता है कि typename संकलन समय जब समारोह instantiated है पर उपलब्ध होना चाहिए, लेकिन मैं टेम्पलेट्स से परिचित नहीं हूं और मैंने टाइपिंग को स्ट्रिंग के रूप में प्राप्त करने का कोई तरीका नहीं देखा है।

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

+2

chris

+0

सहित 'टाइपिड (प्रकार) .name()' का प्रयास करें 'क्या आपको संकलन समय पर सख्ती से इसकी आवश्यकता है? अन्यथा, 'टाइपिड (प्रकार) .name()' मदद कर सकता है। – Philipp

+0

कोई बात नहीं, संकलन-समय की चीज़ नहीं देखी, लेकिन यदि आप इसे प्रिंट कर रहे हैं, तो मुझे यकीन है कि आप इसे रन-टाइम पर समझ सकते हैं। – chris

उत्तर

21

__PRETTY_FUNCTION__ आपकी समस्या का समाधान करना चाहिए नीचे दिए गए कार्यक्रम के लिए उत्पादन होता है:

asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf test<type>::test() [with type = int] 
asfdasdfasdf void tempFunction() [with type = bool] 
asfdasdfasdf void tempFunction() [with type = bool] 
asfdasdfasdf void tempFunction() [with type = bool] 
asfdasdfasdf void tempFunction() [with type = bool] 
asfdasdfasdf void tempFunction() [with type = bool] 
asfdasdfasdf void tempFunction() [with type = bool] 
!!!Hello World!!! 

आप सच में, सच, typename स्ट्रिंग के रूप की जरूरत है, तो आप इस (के बजाय snprintf का उपयोग कर हैक कर सकता है) और '=' और इससे पहले ']' के बाद सबस्ट्रिंग खींचें।

#include <iostream> 
using namespace std; 

template<typename type> 
class test 
{ 
public: 
test() 
{ 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
} 
}; 

template<typename type> 
void tempFunction() 
{ 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__); 
} 

int main() { 
    test<int> test; 

    tempFunction<bool>(); 
    cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! 
    return 0; 
} 
+0

वीएस 15 पर संकलित नहीं है। – shinzou

+2

@kuhaku यह केवल तभी संकलित होगा यदि आप एक कंपाइलर का उपयोग कर रहे हैं जो __PRETTY_FUNCTION__ का समर्थन करता है। [__PRETTY_FUNCTION__] के बारे में विवरण देखने के लिए इस उत्तर की समीक्षा करें (http://stackoverflow.com/questions/4384765/whats-the-difference-between-pretty-function-function-func)। इसके अलावा [यह लिंक] (https://msdn.microsoft.com/library/b0084kay.aspx) आपको दिखाएगा कि एक ही चीज़ करने के लिए विंडोज मैक्रोज़ का उपयोग किया जा सकता है। मुझे संदेह है कि __func__ काम करेगा, लेकिन पुष्टि करने की कोशिश नहीं की है या कोशिश नहीं की है। मैं विशेष रूप से जीसीसी का उपयोग करता हूं, इसलिए मेरे पास पुष्टि करने के लिए पर्यावरण नहीं है। –

+0

नोट: __PRETTY_FUNCTION__ \ _ \ _ PRETTY_FUNCTION \ _ \ _ और __func__ होना चाहिए \ _ \ _ func \ _ \ _ –

11

चूंकि आपने कहा है कि आपको डिबगिंग उद्देश्य के लिए इसकी आवश्यकता होगी, शायद एक रनटाइम समाधान भी स्वीकार्य है। और आपने इसे g ++ के रूप में टैग किया है, इसलिए आप मानक अनुरूप नहीं बनना चाहते हैं।

#include <cxxabi.h> // the libstdc++ used by g++ does contain this header 

template <typename type> 
void print(const type *addr) // you wanted a pointer 
{ 
    char * name = abi::__cxa_demangle(typeid(*addr).name(), 0, 0, NULL); 
    printf("type is: %s\n", name); 
    free(name); 
} 

print(new unsigned long); // prints "type is: unsigned long" 
print(new std::vector<int>); // prints "type is: std::vector<int, std::allocator<int> >" 

संपादित करें: स्मृति रिसाव को सही

यहां उसका का अर्थ है। जेक्स से जेसी।

+0

यह संकलित समय पर काम नहीं करता है, यह सिर्फ नामित नाम – 111111

+0

प्रिंट करता है बस ध्यान रखें कि आप स्मृति को लीक कर रहे हैं क्योंकि 'malloc' को [__cxa_demangle] (http://gcc.gnu.org/onlinedocs/libstdc++ के साथ बुलाया जाता है) /libstdc++-html-USERS-4.3/a01696.html)। –

+0

धन्यवाद रनटाइम समाधान जो मुझे चाहिए उसके लिए काम करता है। –

0

अगर आपके पास प्रकार के एक सेट का इस्तेमाल किया जाना जाता है का दृष्टांत टेम्पलेट हम दृष्टिकोण इस पुराने धागे में वर्णित का उपयोग कर सकते हैं:

(कम से कम रन टाइम पर) stackoverflow.com/questions/1055452

6

Boost.TypeIndex लाइब्रेरी है।

विवरण के लिए boost :: typeindex :: type_id देखें।

यह उपयोग में आसान, क्रॉस-प्लेटफ़ॉर्म है और वास्तविक संकलन-प्रकार समाधान है। आरटीटीआई उपलब्ध होने पर भी यह काम करता है। इसके अलावा अधिकांश कंपाइलर बॉक्स से समर्थित हैं।

+0

ध्यान दें कि यह केवल 'बूस्ट> = 1.56.0' के लिए उपलब्ध है। – BenC

+0

आप सही हैं लेकिन अभी भी उपयोग में आसान है और यह वास्तविक संकलन-प्रकार समाधान है। और यह भी काम करता है भले ही कोई आरटीटीआई जानकारी उपलब्ध न हो। इसके अलावा अधिकांश कंपाइलर बॉक्स से समर्थित हैं। – Andrey

+0

बिल्कुल, इसलिए मेरा +1। लेकिन मुझे आवश्यक अगली सूचना न्यूनतम बूस्ट संस्करण की आवश्यकता थी, क्योंकि बूस्ट के पुराने संस्करणों को वितरित करने वाले वितरण में लाइब्रेरी उपलब्ध नहीं हो सकती है (उदाहरण के लिए उबंटू 12.04), जिसका अर्थ है कि आपको 'बूस्ट <1.56' पर अन्य समाधानों पर वापस आने की आवश्यकता होगी .0' पता चला है। फिर भी, आपके द्वारा जोड़ी गई अतिरिक्त जानकारी आपके उत्तर में होने का हकदार है। – BenC

34

एक उपयोगी संकलन समय नाम पाने के लिए:

जाना चाहिए तुम्हें कुछ अज्ञात प्रकार 'टी' का नाम दिया है। आप कंपाइलर को इसका उपयोग करके इसका प्रकार प्रिंट करने के लिए प्राप्त कर सकते हैं। उदाहरण के लिए:

typedef typename T::something_made_up X; 

त्रुटि संदेश हो जाएगा की तरह:

error: no type named 'something_made_up' in 'Wt::Dbo::ptr<trader::model::Candle>' 

बिट के बाद 'में' प्रकार दिखाता है। (केवल क्लैंग के साथ परीक्षण किया)।

यह ट्रिगर के अन्य तरीके:

bool x = T::nothing; // error: no member named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>' 
using X = typename T::nothing; // error: no type named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>' 
के साथ सी ++ 11

, आप पहले से ही एक वस्तु है और 'decltype' का उपयोग अपने प्रकार प्राप्त करने के लिए कर सकते हैं, तो आप भी चला सकते हैं:

auto obj = creatSomeObject(); 
bool x = decltype(obj)::nothing; // (Where nothing is not a real member). 
+1

यह वास्तव में संकलन समय पर टाइपनामों को प्रिंट करने में मदद करता है जब आपके पास कोड है जो संकलन नहीं कर रहा है! –

+2

वास्तव में सवाल का जवाब देने का एकमात्र प्रतिक्रिया! –

+1

'gcc' के साथ भी ठीक काम करता है। – cartoonist

0

matiu द्वारा प्रदान किए गए एक के समान एक और संकलन समय समाधान, लेकिन थोड़ा सा सहायक समारोह में लिपटे static_assert का उपयोग करने के लिए शायद थोड़ा और वर्णनात्मक होगा।

template<typename T> 
void print_type_in_compilation_error(T&&) 
{ 
    static_assert(std::is_same<T, int>::value && !std::is_same<T, int>::value, "Compilation failed because you wanted to read the type. See below"); 
} 
// usage: 
int I; 
print_type_in_compilation_error(I); 

ऊपर आप एक अच्छे त्रुटि संदेश अन्य जवाब में के रूप में (MSVC और बजना में परीक्षण) दे देंगे, लेकिन कोड IMHO को समझने के लिए बेहतर है।

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