2008-11-19 27 views
22

हालांकि मुझे संदेह है, मैं इस बारे में उत्सुक हूं कि मौजूदा प्रकार से आदिम-प्रकार टेम्पलेट पैरामीटर निकालना संभव है, शायद आरटीटीआई का उपयोग करना।सी ++ टेम्पलेट पैरामीटर निकालें

उदाहरण के लिए:

typedef std::bitset<16> WordSet; 

यह इसे कहीं और कड़ी मेहनत से कोडिंग के बिना उपरोक्त कोड में संख्या 16 को निकालने के लिए संभव होगा? कंपाइलर विशिष्ट कार्यान्वयन का स्वागत है, हालांकि मुझे विशेष रूप से g++ में रूचि है।

उत्तर

37

यह संभव नहीं है।

template<int N> 
struct foo { 
    static const int value = N; 
}; 

और प्रकार

template<typename T> 
struct foo { 
    typedef T type; 
}; 

के लिए आप foo<39>::value या foo<int>::type के रूप में तो यह पहुँच सकते हैं: हमेशा की तरह आप यह कर इस है। वास्तव में,

template<typename> 
struct steal_it; 

template<std::size_t N> 
struct steal_it< std::bitset<N> > { 
    static const std::size_t value = N; 
}; 

इसी सिद्धांत भी प्रकार पैरामीटर के लिए संभव है:

आप एक विशेष प्रकार है, तो आप आंशिक टेम्पलेट विशेषज्ञता का उपयोग कर सकते हैं। अब आप steal_it< std::bitset<16> >::value (आकार_टी का उपयोग करने के लिए नोट, int नहीं!) की तरह किसी भी बिटसेट को पास कर सकते हैं। चूंकि हमारे पास अभी तक कोई भिन्न टेम्पलेट पैरामीटर नहीं है, इसलिए हमें अपने आप को एक विशेष पैरामीटर गिनती तक सीमित करना होगा, और 1 से लेकर एन तक गिनती के लिए steal_it टेम्पलेट विशेषज्ञता दोहराएं। एक और कठिनाई उन प्रकारों को स्कैन करना है जिनमें मिश्रित पैरामीटर (प्रकार और गैर- प्रकार पैरामीटर)। यह हल करने के लिए शायद असंभव है।

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

template<typename T> 
char (& getN(T const &))[steal_it<T>::value]; 

int main() { 
    std::bitset<16> b; 
    sizeof getN(b); // assuming you don't know the type, you can use the object 
} 

चाल समारोह टेम्पलेट ऑटो बनाने के लिए है प्रकार को कम करें, और फिर एक वर्ण सरणी के संदर्भ को वापस करें। फ़ंक्शन को परिभाषित करने की आवश्यकता नहीं है, केवल एक चीज की आवश्यकता है।

+0

अच्छी चाल। एक बात हालांकि, आप यह कहकर शुरू करते हैं कि यह कैसे संभव नहीं है, लेकिन फिर यह दिखाने के लिए आगे बढ़ें! :) –

+0

@ रिचर्ड कॉर्डन: मुझे लगता है कि वह कह रहा था कि आरटीटीआई – cdleary

+3

रिचर्ट कॉर्डन का उपयोग करना संभव नहीं है। मेरा मतलब है कि मनमाने ढंग से टेम्पलेट पैरामीटर चुनना आम तौर पर संभव नहीं है। इस पर विचार करें: टेम्पलेट <टेम्पलेट कक्षा, वर्ग, आकार_टी> कक्षा foo; वह चाल उनके प्रकार नहीं मिलेगी :) –

2

std::bitset के मामले में, तुम सिर्फ size() सदस्य फ़ंक्शन का उपयोग कर सकते हैं:

template <int N> 
class Foo 
{ 
public: 
    int size() const { return N; } 
}; 
:

size_t sz = oh_my_word.size(); // sz is now 16 

सामान्य स्थिति में, आप एक सदस्य समारोह जो एक समान तरीके से आकार देता है परिभाषित कर सकते हैं

+0

मैं के साथ तीसरे पक्ष के वर्गों से यह निकालने के बारे में बात कर रहा हूँ कोई 'आकार()' विधि या कुछ भी समान नहीं - इसे केवल स्वयं को जानने के लिए निकालना। कारण यह है कि मैं टाइप किए गए बिटसेट के आकार को प्राप्त करने के लिए सिर्फ एक डमी इंस्टेंस बनाना नहीं चाहता हूं। – cdleary

+0

यह बिटसेट के लिए विशेष रूप से खराब जुर्माना नहीं है, लेकिन अन्य प्रकार भी हो सकते हैं जहां एक डमी प्रकार को तुरंत चालू करना अवांछित या अव्यवहारिक होता है। – cdleary

0

आप तर्क कटौती और अनियमित संदर्भों का उपयोग करके सी ++ 11 में आसानी से ऐसा कर सकते हैं (ध्यान दें कि डेमो सुविधा के लिए सी ++ 14 की परिवर्तनीय टेम्पलेट सुविधा का उपयोग करता है)।

#include <type_traits> 
#include <iostream> 

template<int> 
struct foo {}; 

template<int arg_N> 
struct val { 
    static constexpr auto N = arg_N; 
}; 

template<template <int> typename T, int N> 
constexpr auto extract(const T<N>&) -> val<N>; 

template<typename T> 
constexpr auto extract_N = decltype(extract(std::declval<T>()))::N; 


int main() { 
    std::cout << extract_N<foo<5>>; 
} 

Live demo

0

के रूप में अन्य उत्तर से कहा गया है, std::bitset के लिए आप size() सदस्य समारोह है, जो सही विकल्प, किसी भी अन्य चाल की तुलना में बेहतर होना चाहिए का उपयोग करके आकार प्राप्त कर सकते हैं।

सामान्य मामले के लिए कई प्रस्ताव, लगभग एक मैं नीचे का सुझाव देने के समान थे, लेकिन फिर भी मुझे लगता है कि यह एक है सरल:

template <template<std::size_t> typename T, std::size_t K> 
auto extractSize(const T<K>&) { 
    return K; 
} 

int main() { 
    std::bitset<6> f1; 
    std::bitset<13> f2; 
    std::cout << extractSize(f1) << std::endl; 
    std::cout << extractSize(f2) << std::endl; 
} 
संबंधित मुद्दे