आगे कैसे घोषित करें C ++ टेम्पलेट क्लास?


99

निम्नलिखित की तरह एक खाका वर्ग को देखते हुए:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

कोई व्यक्ति इस वर्ग को हेडर फ़ाइल में कैसे घोषित कर सकता है?

जवाबों:


103

यह आप इसे कैसे करेंगे:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

ध्यान दें कि डिफ़ॉल्ट आगे की घोषणा में है और वास्तविक परिभाषा में नहीं है।


अपनी परिभाषा में सूचीबद्ध ऐसे डिफॉल्टरों को एक वर्ग घोषित करना संभव है। मेरा जवाब देखिए।
इलियट

मैं असहमत हूं। मानक कहता है: "एक टेम्पलेट-पैरामीटर को एक ही दायरे में दो अलग-अलग घोषणाओं द्वारा डिफ़ॉल्ट तर्क नहीं दिए जाएंगे" । और मुझे केवल पहली घोषणा में चूक के बारे में कुछ नहीं मिला। इसके अलावा परिभाषा में आगे की घोषणा और चूक के साथ कोड सफलतापूर्वक संकलित और चलता है। क्या आप इस बारे में निश्चित हैं कि आप क्या दावा कर रहे हैं? क्या आप मानक से एक उद्धरण प्रदान कर सकते हैं?
olek stolar

@ इलियट ऐसा लगता है कि यह सच है। मानक [17.1.9] कहता है: " एक टेम्पलेट घोषणा में एक डिफ़ॉल्ट टेम्पलेट-तर्क निर्दिष्ट किया जा सकता है ।" नहीं होना चाहिए, लेकिन हो सकता है इस प्रकार मुझे समझ नहीं आता कि अन्य उत्तर यह दावा क्यों करते हैं कि यह पहली घोषणा में होना चाहिए।
ओलेक स्टोलर

और परिभाषा में चूक होने के लिए यह अधिक सुविधाजनक लगता है।
ओलेक स्टोलर

8

आप केवल टेम्पलेट की पहली घोषणा के लिए एक टेम्पलेट के लिए डिफ़ॉल्ट तर्क की घोषणा कर सकते हैं। यदि आप चाहते हैं कि उपयोगकर्ताओं को एक वर्ग टेम्पलेट घोषित करने की अनुमति दी जाए, तो आपको एक अग्रेषण शीर्ष लेख प्रदान करना चाहिए। यदि आप चूक का उपयोग करके किसी और के वर्ग टेम्पलेट को घोषित करना चाहते हैं, तो आप भाग्य से बाहर हैं!


अपनी परिभाषा में सूचीबद्ध ऐसे डिफॉल्टरों को एक वर्ग घोषित करना संभव है। मेरा जवाब देखिए।
इलियट

मैं असहमत हूं। मानक कहता है: "एक टेम्पलेट-पैरामीटर को एक ही दायरे में दो अलग-अलग घोषणाओं द्वारा डिफ़ॉल्ट तर्क नहीं दिए जाएंगे" । और मुझे केवल पहली घोषणा में चूक के बारे में कुछ नहीं मिला। इसके अलावा परिभाषा में आगे की घोषणा और चूक के साथ कोड सफलतापूर्वक संकलित और चलता है। क्या आप इस बारे में निश्चित हैं कि आप क्या दावा कर रहे हैं? क्या आप मानक से एक उद्धरण प्रदान कर सकते हैं?
olek stolar

3

आप एक टेम्प्लेटेड क्लास की घोषणा कर सकते हैं, जिसकी परिभाषा में डिफॉल्ट तर्क दिए गए हैं, लेकिन जब भी आप क्लास को संदर्भित करते हैं, तो आपको इसके सभी तर्कों को तब तक शामिल करना चाहिए जब तक कि परिभाषा पेश नहीं की जाती।

जैसे। std::vectorइसे शामिल किए बिना उपयोग करें ( std::vectorडिफ़ॉल्ट के साथ दूसरा तर्क परिभाषित किया गया है):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

हम तो बिना वेक्टर सहित इसका उपयोग कर सकते हैं, जैसे:

int main()
{
    Foo(3);
}

और हम इसे उपयोग कर सकते हैं के साथ std::vector , जैसे .:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main()
{
    Foo(std::vector<int>(3));
}

मैं मानकों, लेकिन यह काम करता है की जाँच नहीं की है clang/ gccके साथ -std=c++98अप करने के लिए -std=c++17, इसलिए यदि यह आधिकारिक तौर पर एक मानक नहीं है तो यह अनधिकृत रूप से तो लग रहा है।


शायद आप खाली कोण कोष्ठक भूल जाते हैं Foo<> foo;
ओलेक स्टोलर

@ OleksijPlotnyc'kyj तुम सही हो। धन्यवाद। मैंने वह जोड़ हटा दिया है।
इलियट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.