5

के लिए एक पूर्ण अग्रेषण कन्स्ट्रक्टर कैसे बनाएं, मैं टुपल जैसी चीज बनाने की कोशिश कर रहा हूं, लेकिन मुझे अपने कन्स्ट्रक्टर को लिखने में समस्या आई है।टुपल-जैसी वैरिएडिक क्लास

यहाँ कोड है:

#include <tuple> 

template <typename... Ts> 
struct B { 
    template <typename... ArgTypes> 
    explicit B(ArgTypes&&... args) 
    { 
     static_assert(sizeof...(Ts) == sizeof...(ArgTypes), 
      "Number of arguments does not match."); 
    } 
}; 

struct MyType { 
    MyType() = delete; 
    MyType(int x, const char* y) {} 
}; 

int main() 
{ 
    B   <int, char>    a{2, 'c'};      // works 
    B   <int, bool, MyType, char> b{2, false, {4, "blub"}, 'c'}; // fails 
    std::tuple<int, bool, MyType, char> t{2, false, {4, "blub"}, 'c'}; // works 
} 

अब, यह ठीक काम करता है अगर initializers के रूप में सरल प्रकार गुजरती हैं, लेकिन यह अगर मैं गैर तुच्छ के लिए एक ब्रेस संलग्न प्रारंभकर्ता सूची में तर्क पारित करने के लिए कोशिश नहीं करता है, वस्तु।

जीसीसी-4.7 निम्नलिखित का उत्सर्जन करता है:

vararg_constr.cpp:21:67: error: no matching function for call to 'B<int, bool, MyType, char>::B(<brace-enclosed initializer list>)' 
vararg_constr.cpp:21:67: note: candidates are: 
vararg_constr.cpp:6:14: note: B<Ts>::B(ArgTypes&& ...) [with ArgTypes = {}; Ts = {int, bool, MyType, char}] 
vararg_constr.cpp:6:14: note: candidate expects 0 arguments, 4 provided 

बजना-3.1 निम्नलिखित:

vararg_constr.cpp:21:40: error: no matching constructor for initialization of 
     'B<int, bool, MyType, char>' 
    B   <int, bool, MyType, char> b{2, false,{4, "blub"}, 'c'}; // fails 
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
vararg_constr.cpp:6:14: note: candidate constructor not viable: requires 2 
     arguments, but 4 were provided 
    explicit B(ArgTypes&&... args) 

ठीक है, अब क्या मुझे बहुत बनाता है, बहुत ही उत्सुक है कि यह टपल के लिए काम करता है! मानक के मुताबिक (20.4.2.1) इसमें एक कन्स्ट्रक्टर है, जो मेरी तरह दिखता है।

template <class... Types> 
class tuple { 
public: 
    // ... 

    template <class... UTypes> 
    explicit tuple(UTypes&&...); 

    // ... 
}; 

उसी तरह टुपल ऑब्जेक्ट का निर्माण करते समय, यह काम करता है!

अब मुझे पता करना चाहते हैं:

ए) क्या हो? Std :: tuple इतना खास क्यों है, और क्यों संकलक सही तर्कों को कम नहीं करते हैं?

बी) मैं यह काम कैसे कर सकता हूं?

उत्तर

6

ए) कंपाइलर को क्यों पता होना चाहिए कि {4, "blub"} माइट टाइप प्रकार है और tuple<int, const char*> नहीं है?

निर्माता में टी करने के लिए ArgTypes बी) बदलें:

explicit constexpr tuple(const _Elements&... __elements); 

संपादित:

explicit B(Ts&&... args) 

टपल भी निम्न निर्माता है, बात यह है कि साथ स्थिरांक & निर्माता आर-वैल्यू के साथ कहा जाता है और नहीं। निम्नलिखित पर विचार करें:

template <typename... Ts> 
struct B { 
    explicit B(const Ts&... elements) { std::cout << "A\n"; } 
    template<typename... As, 
      typename = typename std::enable_if<sizeof...(As) == sizeof...(Ts)>::type> 
    explicit B(As&&... elements) { std::cout << "B\n" ;} 
}; 

int main() 
{ 
    MyType m {1, "blub"}; 
    B<int, char>   a{2, 'c'};       // prints B 
    B<bool, MyType, char> b{false, {4, "blub"}, 'c'};   // prints A 
    B<bool, MyType, MyType>c{false, {4, "blub"}, std::move(m)}; // prints A 
} 
+0

ए) कंपाइलर टुपल कन्स्ट्रक्टर के लिए कैसे जानता है कि यह एक ट्यूपल है और मायटाइप नहीं है? बी) क्षमा करें, मुझे थोड़ा सा ट्यूपल पर विस्तारित होना चाहिए था। टुपल को टीएस पर parametrized है ..., लेकिन मैं जिस कन्स्ट्रक्टर के बारे में बात कर रहा हूं वह अतिरिक्त रूप से UTypes पर parametrized है ...। –

+0

मैंने समस्या बनाने के लिए संपादित किया है ए) थोड़ा और स्पष्ट – ipc

+1

ध्यान दें कि भाग ए के लिए, संलग्न टेम्पलेट के पैरामीटर पर '&&' डालने का मतलब अर्थ बदलता है, इसलिए यह अब पूर्ण अग्रेषण नहीं है, लेकिन (संदर्भ तर्क को ' त्स') रूपान्तरण संदर्भ, जो वांछित नहीं हैं। भाग बी के लिए, रावल संदर्भों को lvalue 'const 'के लिए" सही किया गया "है, इसलिए यह आमतौर पर काम करेगा, लेकिन यह अभी भी सही अग्रेषण नहीं है। – Potatoswatter

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