2014-04-21 4 views
8

निम्न प्रोग्राम का निरीक्षण करें जिसमें एक फ़ंक्शन अपेक्षित प्रकार और किसी भी प्रकार को स्वीकार करता है जो उस प्रकार का टाइपपीफ है।मैं दृढ़ता से टाइप किए गए गैर-आदिम प्रकार कैसे टाइप करूं?

//a user defined type 
class Widget{}; 

//a function that takes a Widget 
void function (Widget w){} 

int main(){ 

    //make a typedef (this is C++11 syntax for a typedef. It's the same thing) 
    using Gadget = Widget; 

    //make the two "different types" (well.. they're not really different as you will see) 
    Widget w; 
    Gadget g; 

    //call a function that should ONLY accept Widgets 
    function(w); //works (good) 
    function(g); //<- works (I do not want this to compile though) 

} 

जैसा कि आप देख सकते हैं, एक टाइपिफ़ वास्तव में एक नए प्रकार को अलग नहीं करता है। मैंने सोचा कि इस प्रकार से प्राप्त करने के लिए:

//inherit instead 
class Gadget: public Widget{}; 

//make the two "different types" 
Widget w; 
Gadget g; 

//call the function that should ONLY accept widgets 
function(w); //works (good) 
function(g); //<- works (I do not want this to compile though) 

वही समस्या।

#include <boost/serialization/strong_typedef.hpp> 

//a user defined type 
class Widget{}; 

//a function that takes the user defined type 
void function (Widget w){} 

int main(){ 

    //try to strongly typedef 
    BOOST_STRONG_TYPEDEF(Widget, Gadget) 

    //make the two "different types" 
    Widget w; 
    Gadget g; 

    //call the function that should ONLY accept widgets 
    function(w); 
    function(g); 

} 

त्रुटियों संकलन:

In member function ‘bool main()::Gadget::operator==(const main()::Gadget&) const’: 
error: no match for ‘operator==’ (operand types are ‘const Widget’ and ‘const Widget’) 
    BOOST_STRONG_TYPEDEF(Widget, Gadget) 
^
In member function ‘bool main()::Gadget::operator<(const main()::Gadget&) const’: 
error: no match for ‘operator<’ (operand types are ‘const Widget’ and ‘const Widget’) 
    BOOST_STRONG_TYPEDEF(Widget, Gadget) 
^

जाहिर BOOST_STRONG_TYPEDEF केवल आदिम प्रकार पर काम करता है
बढ़ावा को देखते हुए, मैं एक मजबूत typedef की कोशिश करने के बारे में सोचा।

//I want the functionality, but these are NOT the same type! 
class Gadget: public Widget{ 
    operator Widget() = delete; 
}; 

कि या तो काम नहीं किया:
मैं विरासत फिर से करते हैं, लेकिन अंतर्निहित रूपांतरण रोकने की कोशिश की।

सवाल:

  1. strong_typedef केवल आदिम प्रकार पर काम क्यों बढ़ावा देता है?
  2. मजबूत_typef को बढ़ावा देने के समान कार्यक्षमता प्राप्त करने के लिए मैं एक गैर-आदिम प्रकार को 'टाइपिफ़' कैसे कर सकता हूं?
+1

मुझे लगता है कि मैं 'विजेट विजेटबेस' श्रेणी दूंगा, और 'कक्षा विजेट: सार्वजनिक विजेटबेस' करूँगा; 'कक्षा गैजेट: सार्वजनिक विजेटबेस'। – xis

+0

@zneak: यही है 'BOOST_STRONG_TYPEDEF' करता है। – Deduplicator

+0

@Deduplicator कार्यान्वयन को देखते हुए strong_typedef सदस्य का उपयोग करता है और विरासत नहीं। – pmr

उत्तर

1

शायद आप निजी विरासत और कुछ using एस का उपयोग कर सकते हैं?

class Gadget : Widget { using Widget::Widget; using Widget::foo; ... }; 
+0

मुझे लगता है कि यह एक अच्छा समाधान है कि यह मानने के लिए बहुत अधिक विधियां या डेटा सदस्य नहीं हैं। –

5

असल में आपको एक ही व्यवहार के साथ दो असंबंधित कक्षाओं की आवश्यकता है। मुझे लगता है कि के लिए एक parametrized टेम्पलेट का प्रयोग करेंगे:

template<int tag> class WidgetGadget { ... }; 
typedef WidgetGadget<0> Widget; 
typedef WidgetGadget<1> Gadget; 
3

BOOST_STRONG_TYPEDEF वास्तव में मानता है कि प्रकार equatable (==), आबंटित (=) और कम-से-तुलनीय (<) कर रहे हैं।

यदि आपका प्रकार नहीं है, तो मैक्रो परिणाम कोड में संकलित नहीं होता है, जैसा कि आपने देखा है। आप अपने स्वयं के मैक्रो को रोल कर सकते हैं या आवश्यक संचालन के लिए कार्यान्वयन प्रदान कर सकते हैं।

आप फरवरी 2012 से इस जवाब में एक CUSTOM_STRONG_TYPEDEF पा सकते हैं: How to use comparison operators on variant with contained types?, जो स्पष्ट रूप से आपके उपयोग के मामले के लिए और अधिक स्पष्ट उदाहरण बनाया डिफ़ॉल्ट तुलना व्यवहार

अद्यतन हो रही बचा जाता है, यह Live On Coliru देखना

//a user defined type 
class Widget{}; 
class Frobnicator{}; 

///////////////////////////////////////////////////// 
// copied and reduced from boost/strong_typedef.hpp 
#define CUSTOM_STRONG_TYPEDEF(T, D)         \ 
struct D               \ 
    /*: boost::totally_ordered1< D   */      \ 
    /*, boost::totally_ordered2< D, T  */      \ 
    /*> >         */      \ 
{                 \ 
    T t;               \ 
    explicit D(const T t_) : t(t_) {};        \ 
    D(){};               \ 
    D(const D & t_) : t(t_.t){}          \ 
    D & operator=(const D & rhs) { t = rhs.t; return *this;}  \ 
    D & operator=(const T & rhs) { t = rhs; return *this;}   \ 
    explicit operator const T &() const {return t; }    \ 
    explicit operator T &() { return t; }       \ 
    /*bool operator==(const D & rhs) const { return t == rhs.t; } */\ 
    /*bool operator<(const D & rhs) const { return t < rhs.t; } */\ 
}; 

CUSTOM_STRONG_TYPEDEF(Widget, Gadget) 
CUSTOM_STRONG_TYPEDEF(Frobnicator, Normalcy) 

void acceptWidget(Widget){} 
void acceptGadget(Gadget){} 
void acceptFrobnicator(Frobnicator){} 
void acceptNormalcy(Normalcy){} 

int main(){ 

    //make the two "different types" (well.. they're not really different as you will see) 
    Widget w; 
    Gadget g; 

    //call a function that should ONLY accept Widgets 
    acceptWidget(w); //works (good) 
    acceptGadget(g); 

    //acceptWidget(g); // Error 
    //acceptGadget(w); // Error 
    // but we can enjoy conversions if we summon them 
    acceptWidget(static_cast<Widget&>(g)); 

    Frobnicator f; 
    Normalcy n; 
    acceptFrobnicator(f); 
    acceptNormalcy(n); 

} 
+0

मूल प्रश्न में दी गई समस्या के लिए काम करने के लिए, किसी को ऑपरेटर टी के लिए पिछले दो तरीकों पर टिप्पणी करने की आवश्यकता होगी। यह एक अच्छा समाधान है, लेकिन इसे विभिन्न प्रकारों को संभालने के लिए बार-बार फिर से लिखा जाना होगा, और इस प्रकार मैक्रोज़ को विशिष्ट रूप से नामित करना होगा। –

+0

मुझे नहीं लगता कि आपका क्या मतलब है। मैं मुख्य रूप से सिर्फ दूसरे जवाब उद्धृत किया। लेकिन, 'स्पष्ट' रूपांतरण करने से, और, आपको इसे और अधिक लिखने की आवश्यकता नहीं है? मेरा जवाब अपडेट किया गया। इसे देखें [कोलिरु पर लाइव] (http://coliru.stacked-crooked.com/a/458fdbd342cb09e6) ** – sehe

+0

आह! मैं अब स्पष्ट के बारे में देखता हूं। मैंने यह उदाहरण देने के लिए आपके उदाहरण प्रोग्राम पर जोड़ा कि यह मैक्रो केवल एक प्रकार की कक्षा कार्यक्षमता के लिए कैसे उपयोग किया जा सकता है। इस प्रकार मुझे इन विभिन्न मामलों को संभालने के लिए एकाधिक मैक्रोज़ लिखना होगा। http://coliru.stacked-crooked.com/a/8d80373ebd596c61 –

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