जैसा कि मैं समझता हूं, आपकी समस्या का मूल यह है कि अभिव्यक्ति टेम्पलेट अस्थायी में कुछ अन्य अस्थायी लोगों के संदर्भ/पॉइंटर्स हो सकते हैं। और ऑटो & & का उपयोग करके हम केवल अभिव्यक्ति टेम्पलेट का जीवन अस्थायी रूप से बढ़ाते हैं, लेकिन अस्थायी जीवनकाल का संदर्भ नहीं है। क्या यह सही है?
उदाहरण के लिए, this आपके मामले में है?
#include <iostream>
#include <deque>
#include <algorithm>
#include <utility>
#include <memory>
using namespace std;
deque<bool> pool;
class ExpressionTemp;
class Scalar
{
bool *alive;
friend class ExpressionTemp;
Scalar(const Scalar&);
Scalar &operator=(const Scalar&);
Scalar &operator=(Scalar&&);
public:
Scalar()
{
pool.push_back(true);
alive=&pool.back();
}
Scalar(Scalar &&rhs)
: alive(0)
{
swap(alive,rhs.alive);
}
~Scalar()
{
if(alive)
(*alive)=false;
}
};
class ExpressionTemp
{
bool *operand_alive;
public:
ExpressionTemp(const Scalar &s)
: operand_alive(s.alive)
{
}
void do_job()
{
if(*operand_alive)
cout << "captured operand is alive" << endl;
else
cout << "captured operand is DEAD!" << endl;
}
};
ExpressionTemp expression(const Scalar &s)
{
return {s};
}
int main()
{
{
expression(Scalar()).do_job(); // OK
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job(); // OK, lv is still alive
}
{
auto &&rvref=expression(Scalar());
rvref.do_job(); // referencing to dead temporary
}
return 0;
}
यदि हाँ तो संभव समाधान में से एक, अभिव्यक्ति टेम्पलेट temporaries जो temporaries से चले गए संसाधनों पकड़ के विशेष प्रकार का बनाना है।
उदाहरण के लिए, this दृष्टिकोण (आप फिर से बग केस प्राप्त करने के लिए BUG_CASE मैक्रो परिभाषित कर सकते हैं) की जांच करें।
//#define BUG_CASE
#include <iostream>
#include <deque>
#include <algorithm>
#include <utility>
#include <memory>
using namespace std;
deque<bool> pool;
class ExpressionTemp;
class Scalar
{
bool *alive;
friend class ExpressionTemp;
Scalar(const Scalar&);
Scalar &operator=(const Scalar&);
Scalar &operator=(Scalar&&);
public:
Scalar()
{
pool.push_back(true);
alive=&pool.back();
}
Scalar(Scalar &&rhs)
: alive(0)
{
swap(alive,rhs.alive);
}
~Scalar()
{
if(alive)
(*alive)=false;
}
};
class ExpressionTemp
{
#ifndef BUG_CASE
unique_ptr<Scalar> resource; // can be in separate type
#endif
bool *operand_alive;
public:
ExpressionTemp(const Scalar &s)
: operand_alive(s.alive)
{
}
#ifndef BUG_CASE
ExpressionTemp(Scalar &&s)
: resource(new Scalar(move(s))), operand_alive(resource->alive)
{
}
#endif
void do_job()
{
if(*operand_alive)
cout << "captured operand is alive" << endl;
else
cout << "captured operand is DEAD!" << endl;
}
};
template<typename T>
ExpressionTemp expression(T &&s)
{
return {forward<T>(s)};
}
int main()
{
{
expression(Scalar()).do_job(); // OK, Scalar is moved to temporary
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job(); // OK, lv is still alive
}
{
auto &&rvref=expression(Scalar());
rvref.do_job(); // OK, Scalar is moved into rvref
}
return 0;
}
आपका ऑपरेटर/समारोह भार के different types वापस आ सकते हैं, टी पर & &/स्थिरांक टी & तर्कों के आधार:
#include <iostream>
#include <ostream>
using namespace std;
int test(int&&)
{
return 1;
}
double test(const int&)
{
return 2.5;
};
int main()
{
int t;
cout << test(t) << endl;
cout << test(0) << endl;
return 0;
}
तो, आपकी अभिव्यक्ति टेम्पलेट अस्थायी नहीं है जब संसाधनों temporaries से ले जाया गया है - यह है आकार प्रभावित नहीं होगा।
स्रोत
2012-10-21 14:14:30
यदि आप इस तरह के बाध्यकारी को मना करते हैं, तो 'ऑपरेटर + (अभिव्यक्ति_टम्प्लेट कॉन्स और, अभिव्यक्ति_टैम्पप्लेट कॉन्स एंड)' संकलित नहीं होगा। –
@ आर। मार्टिनिन्हो फर्नांडीस: 'expression_template const &' द्वारा 'ऑपरेटर +' को अपने तर्क क्यों लेना चाहिए? मैं कल्पना कर सकता हूं कि 'ऑपरेटर +' किसी प्रकार की प्रॉक्सी के माध्यम से अपने तर्क ले सकता है जो अभी भी 'कॉन्स्ट रेफरेंस' को अभिव्यक्ति टेम्पलेट्स के लिए असुरक्षित रूप से बाध्य नहीं करेगा। (मैं यह नहीं कह रहा कि यह संभव है, लेकिन कम से कम यह असंभव नहीं है)। – Mankarse
@Mankarse आप निहित रूपांतरण और टेम्पलेट प्रकार की कटौती को मिश्रित नहीं कर सकते हैं। चूंकि आपको 'ऑपरेटर +' के लिए काम करने के लिए टाइप कटौती चुननी है, इसलिए इसके लिए तर्क अभिव्यक्ति टेम्पलेट का प्रकार होना चाहिए। (जब तक कि मैं "कुछ प्रकार की प्रॉक्सी" से आपका मतलब समझ नहीं पा रहा हूं) –