2013-03-01 11 views
14

मैं एक सूचक के रूप में टेम्पलेट पैरामीटर के रूप में एक वर्ग के सदस्य के लिए उपयोग करना चाहते हैं: MyStruct<SomeClass, SomeResult, &SomeClass::value> variable काम करता है की तरह इस struct ठीक का उपयोगसूचक टेम्पलेट पैरामीटर के रूप में

template <class Class, class Result, Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

, लेकिन मुझे पसंद नहीं है मुझे SomeClass और SomeResult निर्दिष्ट करना होगा।

यदि संभव हो तो MyStruct<&SomeClass::value> variable का उपयोग करना चाहूंगा, लेकिन किसी भी कक्षा को पारित करने की क्षमता खोने के बिना और कोई परिणाम प्रकार नहीं है।

मैं निम्नलिखित कोशिश की, लेकिन वाक्य रचना अवैध है:

template <class Class, class Result> 
template <Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

error: too many template-parameter-lists

मैं एक सहायक समारोह (है कि वास्तव में बजना में काम करता है, लेकिन जीसीसी से इनकार कर दिया है) उपयोग करने की कोशिश:

template <class Class, class Result> 
static constexpr auto makeMyStruct(Result Class::*member) -> 
MyStruct<Class, Result, member> { 
    // ... 
} 

error: use of parameter `member' outside function body
error: template argument 3 is invalid

क्या यह आसान MyStruct<&SomeClass::value> होना संभव है, और यदि ऐसा है, तो कैसे?

संबंधित सवाल है कि मेरे सवाल का समाधान नहीं:

+0

डुप? http://stackoverflow.com/questions/5628121/is-it-possible-to-emulate-templateauto-x – GManNickG

+0

@GManNickG मुझे यकीन नहीं है कि मेरा प्रश्न उस दूसरे प्रश्न पर उबाल जाए। मेरा बहुत संकीर्ण है, और मैक्रो का उपयोग करके मैं बहुत खुश नहीं हूं। – kay

+1

शब्द * पॉइंटर-टू-सदस्य *, नहीं * संदर्भ * सदस्य है। संदर्भ और पॉइंटर्स भाषा में काफी अलग हैं (ठीक है, नहीं * वह * अलग है, लेकिन फिर भी वही नहीं है) –

उत्तर

2

यह सी ++ 11 में एक समाधान हो सकता है:

आप निम्न सामान्य प्रकार के लक्षण को परिभाषित कर सकते हैं:

template<class T> 
struct remove_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct remove_member_pointer<T Parent::*> { 
    typedef T type; 
}; 

template<class T> 
struct baseof_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct baseof_member_pointer<T Parent::*> { 
    typedef Parent type; 
}; 

अब आप हर struct के लिए एक अतिरिक्त, 4-लाइन आवरण मैक्रो निर्धारित कर सकते हैं:

template<class Class, class Result, Result Class::*Member> 
struct _MyStruct { 
    // ... 
}; 

#define MyStruct(MemberPtr) \ 
    _MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \ 
      remove_member_pointer<decltype(MemberPtr)>::type, \ 
      MemberPtr> 

... और निम्नलिखित तरीके से इसका इस्तेमाल करते हैं:

MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value> 

मैं एक मध्यवर्ती समाधान के रूप में इस का उपयोग करें, जब तक कि हम करने के लिए सी ++ 17 स्विच करें।

+0

दूसरा '_MyStruct <' जगह से बाहर नहीं है? – Quentin

+0

@ क्वांटिन: हां, ज़ाहिर है, धन्यवाद! ;-) – ManuelAtWork

-6

अपने परिणाम वर्ग अपने टेम्पलेट वर्ग के एक बच्चे को बनाओ। सूचक सदस्य मानते हुए सार्वजनिक रूप से अपने परिणाम वर्ग या जो कुछ भी की एक वस्तु है, तो आप इस

template <stuff for this class> :: public result 
{ 
    blah 
} 
11

मेरे प्रश्न का उत्तर अगले आगामी सी ++ मानक के लिए इस पत्र में प्रस्तावित किया गया था की तरह कुछ कर रही द्वारा किसी भी वस्तुओं का उपयोग कर सकते हैं:

इस वाक्य रचना प्रस्तावित किया गया था:

template<using typename T, T t> 
struct some_struct { /* ... */ }; 

some_struct<&A::f> x; 

एक नए वाक्य रचनात्मक निर्माण की आवश्यकता इंगित करती है कि आप अब तक ऐसा नहीं कर सकते हैं।

मुझे आशा है कि n3601 स्वीकार किया जाएगा।:-)

5

C++ 17, टेम्पलेट बहस में auto के अलावा (P0127) साथ में, मुझे लगता है कि तुम अब क्या कर सकते हैं:

template<auto value> 
struct MyStruct {}; 

template<typename Class, typename Result, Result Class::* value> 
struct MyStruct<value> { 
    // add members using Class, Result, and value here 
    using containing_type = Class; 
}; 

typename MyStruct<&Something::theotherthing>::containing_type x = Something(); 
+0

यह क्लैंग 5.0 पर काम करता प्रतीत होता है https://godbolt.org/g/jc3mSl –

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