2009-12-16 15 views
6

निम्नलिखित कोड पर विचार करेंसंकलन समय में सदस्य को सूचक को कैसे सहेजना है?

template<typename T, int N> 
struct A { 
    typedef T value_type; // OK. save T to value_type 
    static const int size = N; // OK. save N to size 
}; 

देखो, यह करता है, तो इस पैरामीटर एक typename या एक पूर्णांक मान है किसी भी टेम्पलेट पैरामीटर को बचाने के लिए संभव है। बात यह है कि सदस्य के लिए सूचक एक ऑफ़सेट है, यानी पूर्णांक। अब मैं संकलन समय में सदस्य के लिए किसी भी सूचक सहेजना चाहते:

struct Foo { 
    int m; 
    int r; 
}; 

template<int Foo::*ptr_to_member> 
struct B { 
    // Next statement DOES NOT WORK! 
    static int Foo::* const saved_ptr_to_member = ptr_to_member; 
}; 

// Example of using 
int main() { 
    typedef B<&Foo::m> Bm; 
    typedef B<&Foo::r> Br; 
    Foo foo; 
    std::cout << (foo.*(Bm::saved_ptr_to_member)); 
} 

कैसे में सदस्य के लिए सूचक को बचाने के लिए समय संकलन? मैं वीएस -2008 का उपयोग करता हूं।

नोट। संकलन समय महत्वपूर्ण है। कृपया रन-टाइम समाधान न लिखें। मुझे यह पता है।

+2

हा-हा, मुझे लगता है Moonshadow नया आज कुछ सीखा ... –

+0

@Jon: मेरे Stroustrup संदर्भ में सदस्यों को प्वाइंटर: वास्तव में, बस chapeter की खोज की 15.5। * भेड़िये * – moonshadow

+0

मैंने अभी उस खंड से एक वाक्य में टाइप किया था जब मुझे एहसास हुआ कि आपने अपना जवाब हटा दिया है। मुझे लगता है कि उनका नाम भ्रमित है हालांकि - वे वास्तव में पॉइंटर्स की तरह कुछ भी नहीं हैं। –

उत्तर

0

एक टेम्पलेट का उपयोग कर क्यों?

#include <cstdio> 

struct Foo { 
    int a; 
    int b; 
} foo = {2, 3}; 

int const (Foo::*mp) = &Foo::b; 

int 
main() { 
    printf("%d\n", foo.*mp); 
    return 0; 
} 

निम्नलिखित जीसीसी-4.4.1 पर इस के लिए mp संकलित (मैं इस समय MSVC के लिए पहुँच नहीं है):

.globl mp 
     .align 4 
     .type mp, @object 
     .size mp, 4 
mp: 
     .long 4 

यह सिर्फ एक सदस्य, करने के लिए ऑफसेट है जो मुझे बहुत संकलित समय लगता है।

टेम्पलेट के साथ, आप वर्ग के बाहर परिभाषा निर्दिष्ट करना होगा:

g++ -O2 -S -o- b.cc | c++filt 

... 

     .weak B<&(Foo::r)>::mp 
     .section  .rodata._ZN1BIXadL_ZN3Foo1rEEEE2mpE,"aG",@progbits,B<&(Foo::r)>::mp,comdat 
     .align 4 
     .type B<&(Foo::r)>::mp, @object 
     .size B<&(Foo::r)>::mp, 4 
B<&(Foo::r)>::mp: 
     .long 4 
     .weak B<&(Foo::m)>::mp 
     .section  .rodata._ZN1BIXadL_ZN3Foo1mEEEE2mpE,"aG",@progbits,B<&(Foo::m)>::mp,comdat 
     .align 4 
     .type B<&(Foo::m)>::mp, @object 
     .size B<&(Foo::m)>::mp, 4 
B<&(Foo::m)>::mp: 
     .zero 4 

हालांकि इस मानक पुस्तकालय के सभी बू आती सुविधाओं reimplementation (std::tr1::mem_fn देखें):

#include <cstdio> 

struct Foo { 
    int m; 
    int r; 
} foo = {2, 3}; 

template<int Foo::*Mem> 
struct B { 
    static int Foo::* const mp; 
}; 

template<int Foo::*Mem> 
int Foo::* const B<Mem>::mp = Mem; 

int main() { 
    typedef B<&Foo::m> Bm; 
    typedef B<&Foo::r> Br; 
    printf("%d, %d\n", foo.*(Bm::mp), foo.*(Br::mp)); 
} 

कौन सा को संकलित करता है।

+1

आप बस मेरे प्रश्न को समझ नहीं सकते हैं। –

+0

फिर कृपया अपने प्रश्न को स्पष्ट करें, बहुत से लोग एक ही नाव में लगते हैं। –

+0

नाराज मत करो। मैं एक प्रकार या पूर्णांक के रूप में टेम्पलेट वर्ग में सदस्य को सूचक को सहेजना चाहता हूं। मुझे सदस्य लक्षणों के लिए एक सूचक * प्रकार के गुणों की आवश्यकता है। –

1

आप नहीं कर सकते।

लेकिन आप इसके बजाय functionoid का उपयोग कर सकते हैं। यह एक संकलन-समय समाधान हो सकता है। और क्योंकि कंपाइलर चीजों को रेखांकित कर सकता है, यह संभवतः किसी सदस्य फ़ंक्शन के सूचक से भी तेज़ है। उदाहरण:

struct Foo { 
    int m; 
    int r; 
}; 

struct FooM { 
    static int call(Foo const &foo) const { return foo.m; } 
} 

struct FooR { 
    static int call(Foo const &foo) const { return foo.r; } 
} 

template<typename FooFun> 
struct B { 
    typedef FooFun foo_fun; 
    int call_foo_fun(Foo const &foo) { return foo_fun::call(foo); } 
}; 

// Example of using 
int main() { 
    typedef B<FooM> Bm; 
    typedef B<FooR> Br; 
    Foo foo; 
    std::cout << Bm.call_foo_fun(foo); 
} 

अनचाहे, लेकिन आपको विचार मिलता है।

0

आप संरचना की परिभाषा के अंदर एक स्थिर सदस्य को प्रारंभ नहीं कर सकते हैं। यह इस तरह से बाहर घोषित किए जाने की आवश्यकता है (जो संभव है कि आप टेम्पलेट के साथ इरादा नहीं है, लेकिन वैसे भी):

struct Foo { 
    int m; 
    int r; 
}; 

template<int Foo::*ptr_to_member> 
struct B { 
    static int Foo::* const saved_ptr_to_member; 
}; 

int Foo::* const B<&Foo::m>::saved_ptr_to_member = &Foo::m; 
int Foo::* const B<&Foo::r>::saved_ptr_to_member = &Foo::r; 

// Example of using 
int main() { 
    typedef B<&Foo::m> Bm; 
    typedef B<&Foo::r> Br; 
    Foo foo; 
    std::cout << (foo.*(Bm::saved_ptr_to_member)); 
} 
+0

1) यह रन-टाइम समाधान है। 2) यह विधि टेम्पलेट्स के फायदों का उपयोग नहीं करती है। मुझे नई संरचना और सदस्यों के मामले में हर बार सदस्य के लिए एक नया सूचक परिभाषित करना होगा। –

+0

1) नहीं, यह नहीं है। 2) सच है, लेकिन वह मूल रूप से डिज़ाइन था, अब संकलक इसे समझने के तरीके में लिखा गया है। मुझे यहां पहली बार टेम्पलेट का उपयोग करने का कोई कारण नहीं दिख रहा है, बस इसे एक गैर-स्थैतिक सदस्य और एक निर्णायक कन्स्ट्रक्टर के साथ एक वर्ग बनाएं और आप कर चुके हैं। बहुत आसान ... – user231967

1

'संकलन-समय महत्वपूर्ण क्यों है' (विकल्पों का सुझाव देने में मदद करता है) के बारे में अधिक विस्तृत स्पष्टीकरण होना अच्छा लगेगा। लेकिन मेरी धारणा के लिए आप को को पॉइंटर-टू-सदस्य के साथ संकलित समय करने की आवश्यकता है, तो आप वास्तव में कर सकते हैं। मेरा संस्करण थॉमस का सुझाव है कि कुछ सी ++ दर्शन के साथ मिश्रित है। सबसे पहले परिभाषित करने देता है:

template <typename T, T v> 
struct val 
{}; 

इस struct टेम्पलेट प्रभावी रूप से के रूप में संकलन समय मूल्य की सेवा कर सकते हैं, और आप "स्थिर मूल्य = वी," की जरूरत नहीं है, यह या तो संकलन या चलाने के समय में उपयोग करने के लिए।पर विचार करें:

template <int n> 
struct Foo 
{ 
    //something dependent on n 
}; 

और

template <typename T> 
struct Bar; 

template <int n> 
struct Bar <val <int, n> > 
{ 
    //something dependent of n 
}; 

फू और बार कार्यात्मक रूप से बराबर कर रहे हैं, हर टेम्पलेट मेटा-kadabra जो फू साथ किया जा सकता भी बार साथ किया जा सकता है (बस पारित बजाय वैल एन)। एक ही vay आप वैल <> में सदस्य के लिए सूचक पैक कर सकते हैं:

val <typeof (&My::a), &My::a> 

इन (बढ़ावा :: एमपीएल :: कुछ की तरह) अब प्रकार सूची में संग्रहित किया जा सकता समय मान संकलन, की तुलना में, बदल, आदि, सब कुछ संकलित समय। और जब आप अंत में उन्हें सूचक करने वाली सदस्य रन टाइम पर के रूप में उपयोग करना चाहते हैं जाएगा, बस एक समारोह टेम्पलेट को परिभाषित:

template <typename T, T value> 
T 
extract (val <T, value>) 
{ 
    return value; 
} 

और प्रयोग यह:

typedef val <typeof (A::i), A::i> a_i; 

A a; 
std::cout << (a .* extract (a_i())); 

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

template <typename M, typename C> 
typename mem_type <M>::value & 
mem_apply (C &c) 
{ 
    M m; 
    return c .* extract (m); 
} 

जहां mem_type वर्ग टेम्पलेट जो सदस्य के प्रकार से संदर्भित किया जाता निकालता है एम तब उपयोग होगा:

std::cout << mem_apply <a_i> (a); 
संबंधित मुद्दे