मेरी समस्या से पहले कुछ हद तक संबंधित एक प्रश्न था, जो टेम्पलेट वर्ग से संबंधित था, जो एक विधि पर std::enable_if का उपयोग करता था, जिसे कक्षा प्रोटोटाइप में घोषित किया जाता है, लेकिन वास्तविक कार्यान्वयन बाहर किया जाता है।

स्रोत: क्लास डेफिनिशन के बाहर enable_if के साथ फंक्शन इंप्लीमेंटेशन

मैं कुछ ऐसा ही करना चाहता हूं, लेकिन क्लास कंस्ट्रक्टर के साथ, जिसे मैं std::enable_if मेटाफंक्शन के साथ बाहरी टेम्प्लेट क्लास को परिभाषित करना चाहता हूं।

template <typename T>
using EnableIfArithmetic = typename std::enable_if<std::is_arithmetic<T>::value, void>::type;

template <typename NumericType>
class SomeClass {
public:
    // constructor definition
    template <typename = EnableIfArithmetic<NumericType>>
    SomeClass() {
        // do some stuff
    }
};

वांछित रूप:

template <typename NumericType>
class SomeClass {
public:
     // constructor declaration
     template <typename = EnableIfArithmetic<NumericType>>
     SomeClass();
};

// constructor definition
template <typename NumericType>
template <typename = EnableIfArithmetic<NumericType>>
SomeClass<NumericType>::SomeClass() {
        // constructor implementation
}

लेकिन मैं त्रुटि संकलित किए बिना इसे ठीक नहीं कर सकता। मैं क्या गलत कर रहा हूं?

-2
L'ahim 24 अक्टूबर 2018, 12:03

1 उत्तर

सबसे बढ़िया उत्तर

टेम्प्लेट तर्कों के लिए डिफ़ॉल्ट मानों को परिभाषाओं में दोहराया नहीं जाना चाहिए। उदाहरण के लिए:

template<typename N>
struct S {
    template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
    S(T);
};

template<typename N>
template<typename T, typename>
S<N>::S(T) { }

जिस तरह से आप SFINAE का उपयोग करते हैं वह सही नहीं है: EnableIfArithmetic कुछ निकाले गए प्रकार (उसी टेम्पलेट में) पर निर्भर होना चाहिए। कृपया देखें यह सवाल< /ए>. उदाहरण के लिए:

template<typename T = N, typename = EnableIfArithmetic<T>>
S() { }

अन्यथा, एक कठिन विफलता होगी:

त्रुटि: 'स्ट्रक्चर एसटीडी :: enable_if' में 'टाइप' नाम का कोई टाइप नहीं

यदि आप कुछ प्रकार N के लिए डिफ़ॉल्ट कंस्ट्रक्टर को अक्षम करना चाहते हैं, तो आप कंस्ट्रक्टर के अंदर static_assert का भी उपयोग कर सकते हैं। हालाँकि, यह SFINAE के अनुकूल नहीं होगा।

template<typename N>
struct S1 {
public:
    template<typename T = N, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
    S1() { }
};

template<typename N>
struct S2 {
public:
    S2() { static_assert(std::is_arithmetic_v<N>); }
};

static_assert(std::is_default_constructible_v<S1<int>>);
static_assert(!std::is_default_constructible_v<S1<void>>);

static_assert(std::is_default_constructible_v<S2<int>>);
static_assert(std::is_default_constructible_v<S2<void>>);
0
Evg 24 अक्टूबर 2018, 10:28