2011-02-01 8 views
6

सी ++ में ऐसा करने का कोई तरीका है, तो मैं उत्सुक हूं।सी ++ फ़ंक्शन से दो टेम्पलेट तर्कों की अधिक सटीक लौट रहा है?

template <typename T> 
class vector {   
public: 
     vector(T a, T b, T c) : x(a), y(b), z(c) {} 

     T x,y,z; 
}; 

और फिर मैं एक टेम्प्लेटेड अलावा ऑपरेटर है:

template <typename A, typename B> 
vector<A> operator +(const vector<A> &a, const vector<B> &b) { 
    return vector<A>(a.x+b.x, a.y+b.y, a.z+b.z); 
} 

मैं उत्सुक हूँ अगर यह है कि ऑपरेटर संशोधित करने के लिए संभव है तो परिणाम की जो भी है चलो कहते हैं कि मैं एक टेम्प्लेटेड वेक्टर वर्ग करते हैं मैन्युअल रूप से इसे विशेषज्ञता देने के अलावा, दो प्रकार ए और बी अधिक सटीक हैं।

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

vector<float>  + vector<double> would produce a vector<double>, 
vector<long double> + vector<float> would produce a vector<long double> 

मेरा अनुमान होगा सी ++ में इस के लिए कोई स्वचालित समर्थन उपलब्ध न हो, लेकिन मैंने सोचा कि मैं पूछना चाहते हैं।

उत्तर

9

लाइब्रेरी के रूप में कोई अंतर्निहित समर्थन नहीं है, लेकिन आप इसे सशर्त (?:) ऑपरेटर का उपयोग करके पूरा कर सकते हैं।

एक अन्य उत्तर के जवाब में, जोहान्स शैब ने a promote<T, U> template पोस्ट किया जो तर्क को काफी अच्छी तरह से लपेटता है। टेम्पलेट के साथ, आप लिखने के लिए सक्षम होना चाहिए:

template <typename A, typename B> 
vector< typename promote<A, B>::type > 
operator+(const vector<A> &a, const vector<B> &b) 
{  
    return vector< typename promote<A, B>::type >(a.x+b.x, a.y+b.y, a.z+b.z); 
} 
+1

' को बढ़ावा दें :: टाइप करें – wilhelmtell

+0

@ विल्हेल्मटेल: धन्यवाद। –

+0

लिंक के लिए धन्यवाद, मैंने जोहान्स से उस मोती को याद किया था (यह आदमी पागल है: पी) –

-1

तुम कभी यह पूरा करने में सक्षम हो जाएगा: बड़े पैमाने पर प्रवंचना बिना या अपने खुद के डिजाइन के कुछ उपकरण के लिए एक सूचक लौटने क्योंकि operator+ एक प्रकार है कि संकलन समय पर जाना जाता है लौटना चाहिए

vector<float> + vector<double> would produce a vector<double>

। आप रन-टाइम पर निर्धारित एक प्रकार को वापस करने के लिए कह रहे हैं।

+4

:

template <typename A, typename B> typename greater<A, B>::type operator +(const vector<A> &a, const vector<B> &b) { typedef typename greater<A, B>::type type; return type(a.x+b.x, a.y+b.y, a.z+b.z); } 

ऑनलाइन प्रदर्शन देखें टेम्पलेट्स specia हैं संकलन समय पर lized, कोई कारण नहीं है कि संकलक 'वेक्टर ' और एक 'वेक्टर ' स्वीकार करने और एक 'वेक्टर ' वापस करने के लिए एक अधिभार नहीं बना सकता है। यह चाल प्रत्येक संयोजन के लिए स्रोत कोड के दोहराव के बिना ऐसा करने के लिए हो रही है। –

7
C++ 0x में

, आप कह सकते हैं:

template <typename A, typename B> 
auto operator +(const vector<A> &a, const vector<B> &b) -> vector<decltype(a.x + b.x)> 
{ 
    //... 
} 

सी ++ 03 में, आप हालांकि आप एक पुन: प्रयोज्य op_traits योजना है कि लागू किया जा सकता में कर सकते हैं सभी संयोजनों अपने आप को परिभाषित करने की जरूरत, विभिन्न ऑपरेटरों के विभिन्न प्रकार के लिए। James McNellis provides some details on this in his answer

+0

@ विल्हेल्मटेल: यह सबसे आसान समाधान है। सी ++ 03 इस तरह से कहीं भी दूरस्थ रूप से कुछ भी ऑफर नहीं करता है। – Puppy

1

टेम्पलेट विशेषज्ञताओं

template< typename A > 
struct TypePrecision { 
    static const int precisionLevel; 
}; 

template< typename A > 
const int TypePrecision<A>::precisionLevel = 0; 


template<> 
struct TypePrecision<float> { 
    static const int precisionLevel; 
}; 
template<> 
struct TypePrecision< long float > { 
    static const int precisionLevel; 
}; 
    template<> 
struct TypePrecision<double> { 
    static const int precisionLevel; 
}; 
template<> 
struct TypePrecision< long double > { 
    static const int precisionLevel; 
}; 

template<> 
const int TypePrecision<float>::precisionLevel = 1; 
template<> 
const int TypePrecision< long float >::precisionLevel = 2; 
template<> 
const int TypePrecision<double>::precisionLevel = 3; 
template<> 
const int TypePrecision< long double >::precisionLevel = 4; 

तो फिर तुम इस का उपयोग एक HigherPrecisionType बनाने के लिए के साथ ऐसा करना एक अपेक्षाकृत आसान तरीका नहीं है

template < typename A , typename B > 
struct HigherPrecisionType 
{ 
    static const int APrecision; 
    static const int BPrecision; 
}; 

template < typename A , typename B > 
const int HigherPrecisionType< A, B >::APrecision= TypePrecision<A>::precisionLevel; 

template < typename A , typename B > 
const int HigherPrecisionType< A, B >::BPrecision= TypePrecision<B>::precisionLevel; 

मुझे यकीन नहीं है कि एप्राइपिएट प्रकार के लिए विशेषज्ञता में टाइपिफ़ प्राप्त करने के लिए इनकी तुलना कैसे करें। लेकिन मुझे उम्मीद है कि आपको

+0

यह दृष्टिकोण काम करता है और मैंने पहले कुछ ऐसा उपयोग किया है। आपको कुछ और टेम्पलेट गोंद की आवश्यकता होती है जो दो प्रकार लेता है और "सशर्त" टाइपिफ़ करने के लिए अपने परिशुद्धता स्तर की तुलना करता है, लेकिन यह बहुत व्यवहार्य है। – Flexo

+0

धन्यवाद, मैं तुलनात्मक भाग – lurscher

+0

तुलना करने के बारे में सिर्फ खाली हूं, यह चाल एक घटाव और फिर आंशिक विशेषज्ञता है। – Flexo

3

आंद्रेई अलेक्जेंड्रेस्कू ने 1 अप्रैल 2001 डीडीजे लेख Generic: Min and Max Redivivus में इस पर चर्चा की।

संक्षेप में, सामान्य समस्या बहुत जटिल है।

एंड्री ने समर्थन कोड की 80 लाइनों का उपयोग किया, जो लाइनें लोकी लाइब्रेरी पर निर्भर करती हैं।

चीयर्स & hth ,.

0

आप फ़ंक्शन ओवरलोडिंग का उपयोग करके कुछ हद तक अपना लक्ष्य पूरा कर सकते हैं।जिसका अर्थ है कि सामान्य के अलावा:

template <typename A, typename B> 
vector<A> operator +(const vector<A> &a, const vector<B> &b) { 
    return vector<A>(a.x+b.x, a.y+b.y, a.z+b.z); 
} 

आप भी भार के विशिष्ट प्रकार के ऐलान करते हैं और इन तो सामान्य रूप से निर्मित लोगों के बजाय आदत हो:

vector<double> operator +(const vector<float> &a, const vector<double> &b) { 
    return vector<double>(a.x+b.x, a.y+b.y, a.z+b.z); 
} 

आपका दूसरा विकल्प रूपांतरण ऑपरेटरों को लागू करने की होगी आवश्यक प्रकार के लिए अपने वेक्टर टेम्पलेट पर। एक फ्लोट वेक्टर एक ऑपरेटर के माध्यम से एक डबल वेक्टर वापस करने में सक्षम हो।

0

हाँ। यहां सी ++ 03 विधि है:

template < typename T1, typename T2 > 
struct which_return; 

template < typename T > 
struct which_return<T,T> { typedef std::vector<T> type; }; 

template < > 
struct which_return<int,double> { typedef std::vector<double> type; }; 

template < > 
struct which_return<double,int> : which_return<int,double> {}; 

// etc... 
template < typename T1, typename T2 > 
typename which_return<T1,T2>::type operator+ (std::vector<T1> const&, std::vector<T2> const&) 
{ 
    // ... 
} 

स्पष्ट रूप से आप इसे C++ 0x तरीके से कर सकते हैं यदि आप कर सकते हैं।

1

पैटर्न "प्रकार चयन" ("आधुनिक सी ++ डिजाइन" में इसके बारे में पढ़ें) यहां उपयोगी हो सकता है।

template <bool flag, typename T, typename U> 
struct Select { 
    typedef T Result; 
}; 

template <typename T, typename U> 
struct Select<false, T, U> { 
    typedef U Result; 
}; 

... 

template <typename A, typename B> 
vector<Select<sizeof(A) > sizeof(B), A, B>::Result> operator +(const vector<A> &a, const vector<B> &b) { 
    return vector<Select<sizeof(A) > sizeof(B), A, B>::Result>(a.x+b.x, a.y+b.y, a.z+b.z); 
} 
+0

के लिए सिंटैक्टिक चीनी थी, यह संकलित नहीं होगा। 'परिणाम' एक आश्रित नाम है, इसलिए 'टाइपनाम' की आवश्यकता है! – Nawaz

+0

यह बहुत सरल है ... 'आकार (फ्लोट)

1

मैं आकार में अधिक से अधिक प्रकार का चयन कर रहा हूँ:

हेल्पर टेम्पलेट्स:

template<bool b, typename A, typename B> 
struct choose_if 
{ 
    typedef A type; 
};  
template<typename A, typename B> 
struct choose_if<false, A, B> 
{ 
    typedef B type; 
}; 
template<typename A, typename B> 
struct greater 
{ 
    static const bool value = sizeof(A) > sizeof(B); 
    typedef vector<typename choose_if<value, A, B>::type> type; 
}; 

अब इसका इस्तेमाल: http://www.ideone.com/PGyA8

+0

दुर्भाग्य से 'sizeof' एक अच्छा संकेतक नहीं है जिस प्रकार की एक बड़ी श्रृंखला है। जैसे 'आकार (फ्लोट)

+0

@ बेन वोगेट: हाँ। मुझे पता है कि यह सही जवाब नहीं है ... बल्कि कोई कैसे शुरू और आगे बढ़ सकता है। असल में मैं इसे सुधारना चाहता था ... लेकिन ऐसा करने के लिए समय नहीं मिला .. – Nawaz

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