this question पर काम करते समय, मैंने देखा कि std::function
का जीसीसी (v4.7) का कार्यान्वयन मूल्य के अनुसार लिया जाता है जब उसके तर्क चलता है। निम्नलिखित कोड इस व्यवहार को दिखाता है:क्या `std :: function` को इसके तर्कों को स्थानांतरित करने की अनुमति है?
#include <functional>
#include <iostream>
struct CopyableMovable
{
CopyableMovable() { std::cout << "default" << '\n'; }
CopyableMovable(CopyableMovable const &) { std::cout << "copy" << '\n'; }
CopyableMovable(CopyableMovable &&) { std::cout << "move" << '\n'; }
};
void foo(CopyableMovable cm)
{ }
int main()
{
typedef std::function<void(CopyableMovable)> byValue;
byValue fooByValue = foo;
CopyableMovable cm;
fooByValue(cm);
}
// outputs: default copy move move
हम यहाँ देखते कि cm
की एक प्रति किया जाता है (जो उचित लगता है के बाद से byValue
के पैरामीटर मान लिया जाता है), लेकिन फिर वहाँ दो कदम हैं। चूंकि function
cm
की एक प्रति पर काम कर रहा है, तथ्य यह है कि यह अपने तर्क को स्थानांतरित करता है, इसे एक महत्वपूर्ण कार्यान्वयन विस्तार के रूप में देखा जा सकता है। हालांकि, इस व्यवहार कुछ परेशानी when using function
together with bind
कारण बनता है:
#include <functional>
#include <iostream>
struct MoveTracker
{
bool hasBeenMovedFrom;
MoveTracker()
: hasBeenMovedFrom(false)
{}
MoveTracker(MoveTracker const &)
: hasBeenMovedFrom(false)
{}
MoveTracker(MoveTracker && other)
: hasBeenMovedFrom(false)
{
if (other.hasBeenMovedFrom)
{
std::cout << "already moved!" << '\n';
}
else
{
other.hasBeenMovedFrom = true;
}
}
};
void foo(MoveTracker, MoveTracker) {}
int main()
{
using namespace std::placeholders;
std::function<void(MoveTracker)> func = std::bind(foo, _1, _1);
MoveTracker obj;
func(obj); // prints "already moved!"
}
इस व्यवहार मानक द्वारा अनुमति है? std::function
को अपने तर्कों को स्थानांतरित करने की अनुमति है? और यदि हां, तो क्या यह सामान्य है कि हम bind
द्वारा std::function
में प्रति-मानकों के साथ वापस आवरण रैपर को परिवर्तित कर सकते हैं, भले ही यह प्लेसहोल्डर्स की कई घटनाओं से निपटने के दौरान अप्रत्याशित व्यवहार को ट्रिगर करता है?
ऐसा लगता है कि यह मुद्दा 'std :: function' से प्लेसहोल्डर के साथ अधिक है। अर्थात्, तथ्य यह है कि 'टाई' बनाते समय, मूल तर्क से अपेक्षित आउटपुट दोनों में स्थानांतरित किया जाता है। –
दिलचस्प बात यह है कि विज़ुअल सी ++ 11 कंपाइलर पहले उदाहरण में "डिफ़ॉल्ट कॉपी चाल" प्रिंट करता है और "पहले से स्थानांतरित" प्रिंट नहीं करता है! क्षण में। मुझे आश्चर्य है कि क्या यह अतिरिक्त कदम std :: function और/या सही अग्रेषण के आंतरिक कार्यकलापों से हो सकता है। –
@MatthieuM। क्या आप विस्तारित कर सकते हैं? मैं प्लेसहोल्डर के कार्यान्वयन से बहुत परिचित नहीं हूं। यदि मुद्दा प्लेसहोल्डर्स से आता है, तो 'std :: function' का उपयोग करने के बजाय "बाइंड-रैपर" प्रकार को कम करने के लिए 'auto' का उपयोग करते समय समस्या उत्पन्न नहीं होती है? –