मेमने से गैर-अदिश प्रकार में रूपांतरण का अनुरोध किया गया
मैंने इस वर्ग का निर्माण किया है, इसलिए मैं किसी भी प्रकार का मूल्य रख सकता हूं जो या तो निश्चित है या इसका उपयोग किए जाने वाले पुनर्गणना है:
template<typename T>
class Value {
private:
bool fixed;
union {
T value;
std::function<T()> get;
};
public:
Value(const T& value) : fixed(true), value(value) {}
Value(const std::function<T()>& get) : fixed(false), get(get) {}
Value(const T *pointer) : Value([pointer]() { return *pointer; }) {}
~Value() {}
operator T() { return fixed ? value : get(); }
};
निम्नलिखित सभी अभिव्यक्तियाँ ठीक लगती हैं:
Value<double> a = 2.2;
double b = 1.;
double c = a;
Value<double> d = &b;
Value<int> e = Value<int>([]() { return 1.; });
लेकिन जब मैं करने की कोशिश करता हूं:
Value<double> f = []() { return 1.; };
एक संकलन त्रुटि शुरू हो गई है:
error: conversion from 'main()::<lambda()>' to non-scalar type 'Value<double>' requested
आप यहां इस उदाहरण की कोशिश कर सकते हैं ।
असाइनमेंट काम क्यों नहीं करता है T
और std::function<T()>
मैं इसे कैसे बना सकता हूं?
नोट: मैं इस उत्तर से अवगत हूं, लेकिन मुझे स्पष्ट नहीं हुआ कि मैं इस मुद्दे को कैसे ठीक करूं, जैसे कि मैंने स्पष्ट रूप से कंस्ट्रक्टर को कॉल किया था Value<double> e
।
जवाब
T के लिए काम क्यों नियत करता है और std :: function <T ()> और मैं इसे कैसे बना सकता हूं?
आपका कोड असाइनमेंट का उपयोग नहीं करता है, लेकिन आरंभीकरण की प्रतिलिपि बनाएँ और
इसके अलावा, कॉपी-इनिशियलाइज़ेशन में निहित रूपांतरण टी को सीधे इनिशियलाइज़र से उत्पन्न करना चाहिए, जबकि, डायरेक्ट-इनिशियलाइज़ेशन से टी के कंस्ट्रक्टर के तर्क के लिए इनिशियलाइज़र से एक अंतर्निहित रूपांतरण की उम्मीद है।
तो यह काम करने के लिए आपको सीधे लैम्ब्डा को स्वीकार करने के लिए अपना ctor बनाना होगा (यह सरल उदाहरण है):
template<typename T>
class Value {
std::function<T()> get;
public:
template<class Y>
Value(Y lambda ) : get( std::move( lambda ) ) {}
};
लाइव कोड आप संभवतः std::enable_if
C या 20 का उपयोग करके प्रतिबंध को जोड़ना चाहते हैं यदि C ++ 20 को इस ctor के साथ-साथ इस रूप में भी अनुमति दी जाती है कि यह निर्माता अन्य ओवरलोड्स को स्वीकार करने की कोशिश करेगा और क्रिप्टोकरंसी पैदा नहीं करेगा। और इस enable_if टेम्पलेट के अनुसार परम लैम्ब्डा है (विशेष हस्ताक्षर के साथ) यह उतना ही सरल हो सकता है
template<class Y, typename = decltype(std::declval<Y&>()())>
Value(Y lambda ) : get( std::move( lambda ) ) {}
जो C ++ 14 का समर्थन करता है। यहाँ अभी तक एक और जीवित उदाहरण है जहाँ आप देख सकते हैं कि इस निर्माणक का उपयोग प्रकार के आरम्भिक के लिए नहीं किया गया है int
:
Value<double> d2 = 123;
prog.cpp: 9: 5: ध्यान दें: उम्मीदवार टेम्पलेट को नजरअंदाज कर दिया गया: प्रतिस्थापन विफलता [Y = int के साथ]: जिसे ऑब्जेक्ट प्रकार 'int' कहा जाता है, वह फ़ंक्शन या फ़ंक्शन पॉइंटर वेल्यू नहीं है (Y lambda): get (std :: move (lambdaose) )) {}
एक लंबोदर नहीं है std::function
। इसका मतलब है कि जब आप करते हैं
Value<double> f = []() { return 1.; };
आपको []() { return 1.; }
एक में परिवर्तित करने की आवश्यकता है std::function
, जो एक उपयोगकर्ता परिभाषित रूपांतरण है, और फिर आपको std::function
उसे एक में परिवर्तित करने की आवश्यकता है Value<double>
, जो कि एक अन्य उपयोगकर्ता द्वारा परिभाषित रूपांतरण है। यह दो उपयोगकर्ता परिभाषित रूपांतरण है जब आपको केवल एक ऐसे रूपांतरण तक अनुमति दी जाती है। यही कारण है कि कोड संकलित करने में विफल रहता है।