क्यों फ़ंक्शन टेम्पलेट आंशिक रूप से विशेष नहीं हो सकता है?


87

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

मैं तर्क को जानना चाहूंगा कि यह क्यों मना करता है? क्या वे उपयोगी नहीं हैं?

template<typename T, typename U> void f() {}   //allowed!
template<> void f<int, char>()            {}   //allowed!
template<typename T> void f<char, T>()    {}   //not allowed!
template<typename T> void f<T, int>()     {}   //not allowed!

के लिए template<typename T, typename U> void f(T t, U u) {}भी template<> void f(int t, char u) {}अनुमति है।
डैशी

10
मुझे यह दिलचस्प लगता है कि लोग वर्कअराउंड प्रदान करते रहते हैं जब सवाल यह नहीं है कि "मैं एक समान लक्ष्य कैसे प्राप्त कर सकता हूं" लेकिन "इस व्यवहार के पीछे तर्क क्या है" ... मैं खुद इस पसंद का कारण नहीं जानता, लेकिन मैं मानता हूं समिति के पास फंक्शन टेम्प्लेट आंशिक विशेषज्ञता के लिए मना करने का एक कारण होना चाहिए। अब तक "निकटतम" स्पष्टीकरण, जॉर्जी द्वारा पोस्ट किया गया लिंक है, जो केवल फ़ंक्शन के आंशिक "" संभावित "जोखिम" को इंगित करता है जब ओवरलोड मौजूद होते हैं। हालाँकि, मुझे नहीं लगता कि यह इस सुविधा के लिए मना करने का एक कारण है, इसलिए मुझे लगता है कि इस के लिए और अधिक है ..
bartgol

जवाबों:


59

AFAIK जो C ++ 0x में बदल गया है।

मुझे लगता है कि यह सिर्फ एक निरीक्षण था (यह विचार करते हुए कि आप हमेशा staticएक वर्ग के सदस्य के रूप में फ़ंक्शन को रखकर अधिक क्रिया कोड के साथ आंशिक विशेषज्ञता प्रभाव प्राप्त कर सकते हैं )।

आप प्रासंगिक डीआर (दोष रिपोर्ट) देख सकते हैं, यदि कोई है।

EDIT : इसे जाँचते हुए , मुझे लगता है कि अन्य लोगों ने भी माना है कि, लेकिन कोई भी मसौदा मानक में ऐसा कोई समर्थन नहीं पा रहा है। यह SO थ्रेड इंगित करता है कि C ++ 0x में फ़ंक्शन टेम्प्लेट का आंशिक विशेषज्ञता समर्थित नहीं है

EDIT 2 : मेरे द्वारा " staticएक वर्ग के सदस्य के रूप में कार्य को प्रस्तुत करने" का सिर्फ एक उदाहरण है :

#include <iostream>
using namespace std;

// template<typename T, typename U> void f() {}   //allowed!
// template<> void f<int, char>()            {}   //allowed!
// template<typename T> void f<char, T>()    {}   //not allowed!
// template<typename T> void f<T, int>()     {}   //not allowed!

void say( char const s[] ) { std::cout << s << std::endl; }

namespace detail {
    template< class T, class U >
    struct F {
        static void impl() { say( "1. primary template" ); }
    };

    template<>
    struct F<int, char> {
        static void impl() { say( "2. <int, char> explicit specialization" ); }
    };

    template< class T >
    struct F< char, T > {
        static void impl() { say( "3. <char, T> partial specialization" ); }
    };

    template< class T >
    struct F< T, int > {
        static void impl() { say( "4. <T, int> partial specialization" ); }
    };
}  // namespace detail

template< class T, class U >
void f() { detail::F<T, U>::impl(); }    

int main() {
    f<char const*, double>();       // 1
    f<int, char>();                 // 2
    f<char, double>();              // 3
    f<double, int>();               // 4
}

क्या आपके पास n3225 में मानक है? मैंने त्वरित खोज की लेकिन यह नहीं मिल सका: /
Matthieu M.

1
आह क्षमा करें ... एक शब्द याद आ रहा था। मेरे पास दस्तावेज है, लेकिन विशेष पैराग्राफ नहीं मिला । हालांकि आपके संपादन को देखते हुए, मुझे लगता है कि यह सिर्फ इसलिए है क्योंकि यह वहां नहीं है :)
Matthieu M.

3
इसे C ++ 0x में नहीं बदला गया है। मुझे इसकी उपयोगिता पर भी संदेह है। आप हमेशा टेम्पलेट को ओवरलोड कर सकते हैं और आंशिक ऑर्डरिंग का उपयोग कर सकते हैं ।
जोहान्स स्काउब -

1
देर से अद्यतन: आठ साल बाद भी सी ++ में नहीं बदला, और सी ++ 20 में प्रवेश करने के लिए प्रतीत नहीं होता है। हालाँकि, इसके लिए कोई कारण नहीं देखा जा सकता है ...
एकॉनगुआ

यह अवधारणा का अब तक का सबसे व्यापक कार्यान्वयन है, मेरा मानना ​​है कि
विक्टर

18

हालांकि, आप वास्तव में आंशिक कार्य / विधि विशेषज्ञता नहीं कर सकते हैं, हालांकि आप ओवरलोडिंग कर सकते हैं।

template <typename T, typename U>
T fun(U pObj){...}

// acts like partial specialization <T, int> AFAIK 
// (based on Modern C++ Design by Alexandrescu)
template <typename T>
T fun(int pObj){...} 

यह तरीका है लेकिन मुझे नहीं पता कि यह आपको संतुष्ट करता है।


1
वाह मेरा मन तो ऐसे खाकों से भर गया कि मैं सच में भूल गया कि साधारण चीजें कैसे हो सकती हैं :)
जोहान्स

1
दुर्भाग्य से यह मामला नहीं है जब आप फ़ंक्शन को आंशिक रूप से विशेषज्ञता देने के बाद वैरेडिक तर्क पारित करना चाहते हैं .. :(
ग्वांगमु ली

मुझे यकीन नहीं है कि वैरेडिक टेम्प्लेट पास करने से क्या मतलब था, इसलिए मैं जानना चाहता हूं कि यह आंशिक विशेषज्ञता से कैसे अलग है। क्या आप अधिक जानकारी प्रदान कर सकते हैं?
शुरुआती

क्या होगा यदि आप सभी अभिन्न और फ्लोट प्रकारों के लिए सिर्फ दो कार्य चाहते हैं?
दिमित्री डॉकशिन

14

सामान्य तौर पर, ओवरलोडिंग से होने वाली परेशानियों के कारण, फंक्शन टेम्प्लेट्स को विशेषज्ञ बनाने की सिफारिश नहीं की जाती है। यहाँ C / C ++ उपयोगकर्ता जर्नल से एक अच्छा लेख है: http://www.gotw.ca/publications/mill17.htm

और इसमें आपके प्रश्न का ईमानदार उत्तर है:

एक बात के लिए, आप उन्हें आंशिक रूप से विशेषज्ञ नहीं बना सकते हैं - बहुत ज्यादा सिर्फ इसलिए क्योंकि भाषा कहती है कि आप नहीं कर सकते।


3
लेख आंशिक विशेषज्ञता के बारे में नहीं है इसके अलावा यह एक बार उल्लेख किया गया है।
यूरी पिनहोलो

11

चूँकि आप आंशिक रूप से वर्गों का विशेषज्ञ बन सकते हैं, आप एक फ़नकार का उपयोग कर सकते हैं:

#include <iostream>

template < typename dtype , int k > struct fun
{
 int operator()()
 {
  return k ;
 }
} ;

template < typename dtype > struct fun < dtype , 0 >
{
 int operator()()
 {
  return 42 ;
 }
} ;

int main ( int argc , char * argv[] )
{
 std::cout << fun<float,5>()() << std::endl ;
 std::cout << fun<float,0>()() << std::endl ;
}

1
तब आप कॉल करने के लिए एक ही फंक्शन टेम्पलेट का उपयोग कर सकते हैं, जो कि बदसूरत ()()सिंटैक्स से छुटकारा दिलाता है।
tmr232
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.