2011-03-10 7 views
5

क्या "सुंदर" फैशन में टेम्पलेट्स के साथ Named Constructor Idiom का उपयोग करने का कोई तरीका है?नामित कन्स्ट्रक्टर इडियॉम और टेम्पलेट्स?

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

#include <vector> 
using namespace std; 

template< typename T > 
class Foo 
{ 
public: 
    static Foo Copy(const T& arg) 
    { 
     Foo ret; 
     ret.t_copy = arg; 
     return ret; 
    } 

    static Foo CopyClear(const T& arg) 
    { 
     Foo ret; 
     ret.t_copy = arg; 
     ret.t_copy.clear(); 
     return ret; 
    } 

private: 
    T t_copy; 
}; 


int main(int argc, char** argv) 
{ 
    vector<double> vec; 
    vec.push_back(1); 

    // #1: won't compile 
    Foo< vector<double> > a_foo = Foo::CopyClear(vec); 

    // #2: ugly, but works 
    Foo< vector<double> > a_foo = Foo< vector<double> >::CopyClear(vec); 

    return 0; 
} 

मैं किसी भी तरह #1 का सिंटैक्स का उपयोग करना चाहते हैं। #2 काम करता है लेकिन मेरे DRY को गलत तरीके से समझता है।

संपादित करें: Foo का नया, अधिक "यथार्थवादी" संस्करण।

EDIT2: नहीं C++ 0x/C++ 1x मेरे लिए मुझे डर लग रहा :(

+0

जहां # 2 या आप _rvalue_ की बात कर रहे है सही ढंग से कॉल कि अस्पष्ट नहीं है scoped? क्या आपने कन्स्ट्रक्टर में आकार को पार करने जैसे एक और अधिक सुरुचिपूर्ण समाधान पर विचार किया है? – AJG85

+0

टिप्पणियों में मैंने 'CopyClear()' के दूसरे आमंत्रण को # 2 के रूप में चिह्नित किया। – genpfault

उत्तर

3

अपडेट किया गया जवाब

अगर मैं अपने इरादे सही ढंग से समझ, इस चाल करना होगा:

template< typename T > 
class Foo 
{ 
private: 
    friend class FooHelper; 
    size_t sz; 
}; 

class FooHelper 
{ 
public: 
    template< typename T > 
    static Foo<T> Size(const T& arg) 
    { 
     Foo<T> ret; 
     ret.sz = arg.size(); 
     return ret; 
    } 

    template< typename T > 
    static Foo<T> HalfSize(const T& arg) 
    { 
     Foo<T> ret; 
     ret.sz = arg.size()/2; 
     return ret; 
    } 
}; 

यह तो संकलित:

int main(int argc, char** argv) 
{ 
    vector<double> vec; 
    vec.push_back(1); 

    Foo<vector<double>> a_foo = FooHelper::HalfSize(vec); 
} 
+0

दिए गए उदाहरण के लिए मान्य, हालांकि, मुझे लगता है कि ओपी कन्स्ट्रक्टरों के बजाय, अपनी कक्षा में टी का उपयोग करना चाहता है। इसके अलावा, मुझे वास्तविक प्रश्न के किसी भी समाधान के बारे में पता नहीं है, इसलिए यह संभव नहीं है कि आप जिस तरह से बनना चाहते हैं (मुझे गलत हो सकता है)। – dialer

+0

'फू' भी टेम्पलेट किया गया है। – genpfault

+0

@ डियालर, @genpfault: उस मामले में, वह 'फू' स्थिर विधियों से वापस आने के लिए 'टेम्पलेट क्लास बार' बना सकता है और इसकी तत्काल वस्तुओं को वापस कर सकता है। असल में यह टेम्पलेट तर्क प्रकार को दोहराने का मुद्दा वापस लाएगा, लेकिन इस मामले में यह 'Foo '(जिसे" लाइब्रेरी कोड "माना जा सकता है) के अंदर' टी' दोहराया जाएगा। किसी भी तरह, अगर ओपी अधिक जानकारी प्रदान करता है तो हम अपने उत्तरों को अनुकूलित कर सकते हैं। – Jon

3

मुझे नहीं पता लगता है कि एक डीआरवाई समस्या है, इसे एक भाषा प्रतिबंध के रूप में सोचें। आप टेम्पलेट के बिना एक वर्ग फू है, लेकिन आप एक स्थिर विधि से एक नई वस्तु बनाने के लिए चाहते हैं, आप की तरह कुछ करने के लिए चाहते हैं:

Foo a_foo = Foo::HalfSize(something); 

और वहाँ पाठ्यक्रम फू दो बार दोहराए की है।

इसलिए, यहां से पूर्ण वर्ग का नाम Foo< vector<double> > है, इसलिए Foo< vector<double> >::HalfSize() से स्थैतिक विधि प्राप्त करने के लिए तार्किक है, क्योंकि यह सी ++ तरीका है।

3

@ जॉन के उत्तर के अलावा, std::make_pair और std::pair पर इसके संबंध देखें, यदि आपको कक्षा को स्वयं टेम्पलेट होने की आवश्यकता है।

+1

और, 'make_shared' और' shared_ptr' भी। मैं इसे कटौती से लाभ उठाने के लिए टेम्पलेट ऑब्जेक्ट्स बनाने के लिए टेम्पलेट फ़ंक्शंस का उपयोग करने के लिए एक मुहावरे मानता हूं। –

2

यदि आप सी ++ 0x सुविधाओं का उपयोग कर सकते हैं, तो auto कीवर्ड मदद करेगा। क्या कोई कारण है कि Size() और HalfSize() स्थिर विधियां होने की आवश्यकता है? आप उत्परिवर्तित तरीके प्रदान करते हैं sz आप यह कर सकते हैं:

template<class T> 
Foo<T> HalfSize(const T& arg) 
{ 
    Foo<T> ret; 
    ret.setSz(arg.size()/2); // or similar 
    return ret; 
} 

और फिर # 1 थोड़ा और प्राप्य है।

+0

मेरे लिए कोई सी ++ 0x मुझे डर है :( – genpfault

2

सी ++ बचाव के लिए 1x:

auto a_foo = Foo::HalfSize<vector<double>>(vec); 

और, हाँ, दो को बंद करने >> सी ++ 1x में > > के रूप में पार्स कर रहे हैं।

शायद आपके पास एक कंपाइलर के साथ पहले से ही उपलब्ध है।

+0

मेरे लिए कोई सी ++ 1 एक्स मुझे डर है :( – genpfault

+0

@genpfault: आप किस कंपाइलर का उपयोग कर रहे हैं? – sbi

+0

विजुअल सी ++ 2008. – genpfault

3

यह तकनीकी रूप से ठीक है और संभवतः अपने अंत सवाल करने का सबसे सरल जवाब है:

Foo< vector<double> > a_foo = a_foo.CopyClear(vec); 

यह तकनीकी रूप से ठीक क्योंकि CopyClear एक static सदस्य समारोह है।

और कोई तकनीकी समस्या नहीं है, उदा। आप इसके बजाय typedef का उपयोग कर सकते हैं। या केवल उन टेम्पलेट टेम्पलेट्स के रूप में नामस्थान स्कोप पर static सदस्य फ़ंक्शंस डालें। या कुछ सहायक वर्ग में, जैसा कि किसी ने पहले से ही सुझाव दिया है।

लेकिन हालांकि कोई तकनीकी समस्या नहीं है, डिजाइन आदर्श से कम है; यह है, इसे स्पष्ट रूप से (माफ करना), अर्थहीन से थोड़ा बदतर है।

उदाहरण के लिए, CopyClear में, आप एक वेक्टर की प्रतिलिपि क्यों बना रहे हैं और फिर कॉपी परिणाम को छोड़कर क्यों? आपको केवल उस कोड का एक खाली वेक्टर बनाना होगा, जिस प्रकार आपका कोड जानता है।

और उदाहरण के लिए, आप साइड-इफेक्ट मशीनरी क्यों पेश कर रहे हैं?

साइड इफेक्ट्स से बचा जाना चाहिए और हटाया जाना चाहिए, पेश नहीं किया गया।

चीयर्स & hth।,

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