मेरा मतलब कुछ इस तरह है:
int main()
{
void a()
{
// code
}
a();
return 0;
}
मेरा मतलब कुछ इस तरह है:
int main()
{
void a()
{
// code
}
a();
return 0;
}
जवाबों:
C ++ (C ++ 11, C ++ 14, और C ++ 17) के वर्तमान संस्करणों में, आप एक लंबोदर के रूप में कार्यों के अंदर कार्य कर सकते हैं:
int main() {
// This declares a lambda, which can be called just like a function
auto print_message = [](std::string message)
{
std::cout << message << "\n";
};
// Prints "Hello!" 10 times
for(int i = 0; i < 10; i++) {
print_message("Hello!");
}
}
लैंबदास ** कैद-दर-संदर्भ * के माध्यम से स्थानीय चर भी संशोधित कर सकते हैं। कैप्चर-बाय-रेफरेंस के साथ, लैम्ब्डा की लैम्बडा के दायरे में घोषित सभी स्थानीय चर तक पहुंच है। यह उन्हें सामान्य रूप से संशोधित और बदल सकता है।
int main() {
int i = 0;
// Captures i by reference; increments it by one
auto addOne = [&] () {
i++;
};
while(i < 10) {
addOne(); //Add 1 to i
std::cout << i << "\n";
}
}
C ++ सीधे समर्थन नहीं करता है।
उस ने कहा, आपके पास स्थानीय कक्षाएं हो सकती हैं, और उनके कार्य (गैर- staticया static) हो सकते हैं, इसलिए आप इसे कुछ हद तक प्राप्त कर सकते हैं, यद्यपि यह एक कीचड़ का एक सा है:
int main() // it's int, dammit!
{
struct X { // struct's as good as class
static void a()
{
}
};
X::a();
return 0;
}
हालाँकि, मैं प्रैक्सिस पर सवाल उठाऊंगा। सभी जानते हैं (अच्छी तरह से, अब आप जो भी करते हैं :)) C ++ स्थानीय कार्यों का समर्थन नहीं करता है, इसलिए उनका उपयोग उनके नहीं होने के लिए किया जाता है। हालांकि, उनका उपयोग उस कीचड़ में नहीं किया जाता है। मैं यह सुनिश्चित करने के लिए इस कोड पर काफी समय खर्च करूंगा कि यह वास्तव में केवल स्थानीय कार्यों की अनुमति देने के लिए है। अच्छा नही।
int main()औरint main(int argc, char* argv[])
int main()और int main(int argc, char* argv[])समर्थित होना चाहिए और दूसरों का समर्थन किया जा सकता है, लेकिन वे सभी वापस लौट आए हैं।
सभी इरादों और उद्देश्यों के लिए, C ++ लैंबडास : 1 के माध्यम से इसका समर्थन करता है
int main() {
auto f = []() { return 42; };
std::cout << "f() = " << f() << std::endl;
}
यहाँ, fएक लैम्ब्डा ऑब्जेक्ट है जो एक स्थानीय फ़ंक्शन के रूप में कार्य करता है main। फ़ंक्शन को स्थानीय ऑब्जेक्ट तक पहुंचने की अनुमति देने के लिए कैप्चर निर्दिष्ट किया जा सकता है।
पर्दे के पीछे, fएक फंक्शन ऑब्जेक्ट (यानी एक प्रकार की वस्तु जो प्रदान करता है operator()) है। फ़ंक्शन ऑब्जेक्ट प्रकार को लंबर के आधार पर कंपाइलर द्वारा बनाया गया है।
C ++ 11 के बाद से 1
+1मुझसे।
स्थानीय कक्षाओं का उल्लेख पहले ही किया जा चुका है, लेकिन यहां एक ऑपरेटर () अधिभार और एक अनाम वर्ग का उपयोग करते हुए उन्हें स्थानीय कार्यों के रूप में प्रदर्शित करने का एक तरीका दिया गया है:
int main() {
struct {
unsigned int operator() (unsigned int val) const {
return val<=1 ? 1 : val*(*this)(val-1);
}
} fac;
std::cout << fac(5) << '\n';
}
मैं इसे इस्तेमाल करने की सलाह नहीं देता, यह सिर्फ एक मज़ेदार ट्रिक है (कर सकते हैं, लेकिन इमो नहीं होना चाहिए)।
कुछ समय पहले C ++ 11 के उदय के साथ, अब आपके पास स्थानीय कार्य हो सकते हैं जिनका वाक्यविन्यास जावास्क्रिप्ट की थोड़ी याद दिलाता है:
auto fac = [] (unsigned int val) {
return val*42;
};
operator () (unsigned int val), अपने गुम कोष्ठकों का एक सेट।
std::sort(), या std::for_each()।
autoचर घोषित करने के लिए उपयोग नहीं कर सकते । स्ट्रॉस्ट्रुप उदाहरण देता है: function<void(char*b, char*e)> rev=[](char*b, char*e) { if( 1<e-b ) { swap( *b, *--e); rev(++b,e); } };एक स्ट्रिंग दी गई शुरुआत और अंत बिंदुओं को उलटने के लिए।
नहीं।
तुम क्या करने की कोशिश कर रहे हो?
वैकल्पिक हल:
int main(void)
{
struct foo
{
void operator()() { int a = 1; }
};
foo b;
b(); // call the operator()
}
C ++ 11 से शुरू करके आप उचित लैम्ब्डा का उपयोग कर सकते हैं । अधिक विवरण के लिए अन्य उत्तर देखें।
पुराना उत्तर: आप छांट सकते हैं, लेकिन आपको एक डमी क्लास को धोखा देना और उसका उपयोग करना है:
void moo()
{
class dummy
{
public:
static void a() { printf("I'm in a!\n"); }
};
dummy::a();
dummy::a();
}
जैसा कि दूसरों ने उल्लेख किया है, आप gcc में gnu भाषा एक्सटेंशन का उपयोग करके नेस्टेड फ़ंक्शन का उपयोग कर सकते हैं। यदि आप (या आपकी परियोजना) जीसीसी टूलचैन से चिपके रहते हैं, तो आपका कोड जीसीसी कंपाइलर द्वारा लक्षित विभिन्न आर्किटेक्चर के पार ज्यादातर पोर्टेबल होगा।
हालांकि, अगर कोई संभावित आवश्यकता है कि आपको एक अलग टूलकिन के साथ कोड संकलित करने की आवश्यकता हो सकती है, तो मैं ऐसे एक्सटेंशन से दूर रहूंगा।
नेस्टेड फ़ंक्शंस का उपयोग करते समय मैं देखभाल के साथ भी चलना चाहता हूं। वे जटिल की संरचना के प्रबंधन के लिए एक सुंदर समाधान हैं, फिर भी कोड के कोड को ब्लॉक करते हैं (जिसके टुकड़े सामान्य / सामान्य उपयोग के लिए नहीं हैं।) वे नेमस्पेस प्रदूषण को नियंत्रित करने में भी बहुत सहायक होते हैं (स्वाभाविक रूप से जटिल के साथ एक बहुत ही वास्तविक चिंता / क्रिया भाषाओं में लंबी कक्षाएं।)
लेकिन किसी भी चीज की तरह, वे दुरुपयोग के लिए खुले हो सकते हैं।
यह दुखद है कि C / C ++ मानक के रूप में ऐसी सुविधाओं का समर्थन नहीं करता है। अधिकांश पास्कल वेरिएंट और एडा करते हैं (लगभग सभी अल्गोल-आधारित भाषाएँ करते हैं)। जावास्क्रिप्ट के साथ भी। स्काला जैसी आधुनिक भाषाओं के साथ भी। Erlang, Lisp या Python जैसी आदरणीय भाषाओं के साथ भी।
और सी / सी ++ के साथ के रूप में, दुर्भाग्य से, जावा (जिसके साथ मैं अपने अधिकांश जीवित कमाता हूं) नहीं करता है।
मैं यहां जावा का उल्लेख करता हूं क्योंकि मैं कई पोस्टरों को कक्षाओं और कक्षा के तरीकों का उपयोग करने का सुझाव देता हूं ताकि नेस्टेड फ़ंक्शन के विकल्प के रूप में। और यह भी जावा में विशिष्ट समाधान है।
संक्षिप्त उत्तर: नहीं।
ऐसा करना एक वर्ग पदानुक्रम पर कृत्रिम, अनावश्यक जटिलता का परिचय देता है। सभी चीजें समान होने के साथ, आदर्श के लिए एक वास्तविक श्रेणी का प्रतिनिधित्व करते हुए एक वर्ग पदानुक्रम (और इसके नाम और स्कोप को शामिल करना) है।
नेस्टेड फ़ंक्शन "निजी" से निपटने में मदद करते हैं, फ़ंक्शन-फ़ंक्शन जटिलता के भीतर। उन सुविधाओं को कम करते हुए, किसी को उस "निजी" जटिलता को बाहर करने और किसी के क्लास मॉडल के प्रचार से बचने की कोशिश करनी चाहिए।
सॉफ्टवेयर में (और किसी भी इंजीनियरिंग अनुशासन में), मॉडलिंग व्यापार-नापसंद का विषय है। इस प्रकार, वास्तविक जीवन में, उन नियमों (या बल्कि दिशानिर्देशों) के लिए उचित अपवाद होंगे। हालांकि देखभाल के साथ आगे बढ़ें।
C ++ में आपके स्थानीय कार्य नहीं हो सकते। हालाँकि, C ++ 11 में लैम्ब्डा है । लैम्ब्डा मूल रूप से वैरिएबल होते हैं जो फ़ंक्शंस की तरह काम करते हैं।
एक लैम्ब्डा का प्रकार होता है std::function( वास्तव में यह बिल्कुल सच नहीं है , लेकिन ज्यादातर मामलों में आप मान सकते हैं कि यह है)। इस प्रकार का उपयोग करने के लिए, आपको करने की आवश्यकता है #include <functional>। std::functionएक टेम्पलेट है, जो टेम्पलेट तर्क के रूप में रिटर्न प्रकार और तर्क प्रकार को सिंटैक्स के साथ लेता है std::function<ReturnType(ArgumentTypes)। उदाहरण के लिए, std::function<int(std::string, float)>एक लंबोदर एक लौट रहा है intऔर दो तर्क ले रहा है, एक std::stringऔर एक float। सबसे आम एक है std::function<void()>, जो कुछ भी नहीं लौटाता है और कोई तर्क नहीं लेता है।
एक बार एक लंबोदर घोषित होने के बाद, इसे सिंटैक्स का उपयोग करके सामान्य फ़ंक्शन की तरह कहा जाता है lambda(arguments)।
एक लैम्ब्डा को परिभाषित करने के लिए, सिंटैक्स का उपयोग करें [captures](arguments){code}(इसे करने के अन्य तरीके हैं, लेकिन मैं यहां उनका उल्लेख नहीं करूंगा)। argumentsलैम्ब्डा क्या तर्क देता है, और codeवह कोड है जिसे लैम्ब्डा कहे जाने पर चलाया जाना चाहिए। आमतौर पर आप [=]या [&]कब्जा के रूप में डालते हैं । [=]इसका मतलब है कि आप उस मूल्य के दायरे में सभी चरों पर कब्जा कर लेते हैं, जिसका अर्थ मूल्य द्वारा परिभाषित किया गया है, जिसका अर्थ है कि वे उस मूल्य को रखेंगे जो उनके पास था जब लंबोदर घोषित किया गया था। [&]इसका मतलब है कि आप संदर्भ द्वारा सभी चर को दायरे में कैद कर लेते हैं, जिसका अर्थ है कि उनका हमेशा उनका वर्तमान मूल्य होगा, लेकिन यदि वे स्मृति से मिटा दिए जाते हैं, तो प्रोग्राम क्रैश हो जाएगा। यहाँ कुछ उदाहरण हैं:
#include <functional>
#include <iostream>
int main(){
int x = 1;
std::function<void()> lambda1 = [=](){
std::cout << x << std::endl;
};
std::function<void()> lambda2 = [&](){
std::cout << x << std::endl;
};
x = 2;
lambda1(); //Prints 1 since that was the value of x when it was captured and x was captured by value with [=]
lambda2(); //Prints 2 since that's the current value of x and x was captured by value with [&]
std::function<void()> lambda3 = [](){}, lambda4 = [](){}; //I prefer to initialize these since calling an uninitialized lambda is undefined behavior.
//[](){} is the empty lambda.
{
int y = 3; //y will be deleted from the memory at the end of this scope
lambda3 = [=](){
std::cout << y << endl;
};
lambda4 = [&](){
std::cout << y << endl;
};
}
lambda3(); //Prints 3, since that's the value y had when it was captured
lambda4(); //Causes the program to crash, since y was captured by reference and y doesn't exist anymore.
//This is a bit like if you had a pointer to y which now points nowhere because y has been deleted from the memory.
//This is why you should be careful when capturing by reference.
return 0;
}
आप उनके नामों को निर्दिष्ट करके विशिष्ट चर भी पकड़ सकते हैं। केवल उनके नाम को निर्दिष्ट करने से वे मूल्य पर कब्जा कर लेंगे, उनके नाम को &पहले से निर्दिष्ट करके उन्हें संदर्भ द्वारा कैप्चर करेंगे। उदाहरण के लिए, [=, &foo]मूल्य के अलावा सभी चर पर कब्जा कर लेंगे , fooजिसे छोड़कर संदर्भ द्वारा कब्जा कर लिया [&, foo]जाएगा , और संदर्भ द्वारा सभी चर को पकड़ लेंगे , fooजिसके अलावा मूल्य पर कब्जा कर लिया जाएगा। तुम भी केवल विशिष्ट चरों पर कब्जा कर सकते हैं, उदाहरण के लिए [&foo]कब्जा fooसंदर्भ द्वारा और कोई अन्य चर पर कब्जा होगा। तुम भी उपयोग करके कोई चर पर कब्जा कर सकते हैं []। यदि आप एक लैम्ब्डा में वैरिएबल का उपयोग करने का प्रयास करते हैं जिसे आपने कैप्चर नहीं किया है, तो यह संकलित नहीं होगा। यहाँ एक उदाहरण है:
#include <functional>
int main(){
int x = 4, y = 5;
std::function<void(int)> myLambda = [y](int z){
int xSquare = x * x; //Compiler error because x wasn't captured
int ySquare = y * y; //OK because y was captured
int zSquare = z * z; //OK because z is an argument of the lambda
};
return 0;
}
आप एक वैरिएबल का मान नहीं बदल सकते हैं जो लैम्बडा के अंदर वैल्यू द्वारा कैप्चर किया गया था (वैल्यू द्वारा कैप्चर किए गए वेरिएबल constलैम्ब्डा के अंदर एक प्रकार है)। ऐसा करने के लिए, आपको संदर्भ द्वारा चर को पकड़ने की आवश्यकता है। यहाँ एक परीक्षा है:
#include <functional>
int main(){
int x = 3, y = 5;
std::function<void()> myLambda = [x, &y](){
x = 2; //Compiler error because x is captured by value and so it's of type const int inside the lambda
y = 2; //OK because y is captured by reference
};
x = 2; //This is of course OK because we're not inside the lambda
return 0;
}
इसके अलावा, बिन बुलाए लैम्ब्डा को कॉल करना अपरिभाषित व्यवहार है और आमतौर पर इस कार्यक्रम के दुर्घटनाग्रस्त होने का कारण होगा। उदाहरण के लिए, ऐसा कभी न करें:
std::function<void()> lambda;
lambda(); //Undefined behavior because lambda is uninitialized
उदाहरण
यहाँ लैम्बदास का उपयोग करके आप अपने प्रश्न में क्या करना चाहते हैं, इसके लिए कोड दिया गया है:
#include <functional> //Don't forget this, otherwise you won't be able to use the std::function type
int main(){
std::function<void()> a = [](){
// code
}
a();
return 0;
}
यहाँ एक मेमने का एक और अधिक उन्नत उदाहरण दिया गया है:
#include <functional> //For std::function
#include <iostream> //For std::cout
int main(){
int x = 4;
std::function<float(int)> divideByX = [x](int y){
return (float)y / (float)x; //x is a captured variable, y is an argument
}
std::cout << divideByX(3) << std::endl; //Prints 0.75
return 0;
}
नहीं, इसकी अनुमति नहीं है। डिफ़ॉल्ट रूप से न तो C और न ही C ++ इस सुविधा का समर्थन करता है, हालांकि टोनीके बताते हैं (टिप्पणियों में) कि GNU C संकलक के विस्तार हैं जो C में इस व्यवहार को सक्षम करते हैं।
यह सभी तरकीबें स्थानीय कार्यों के रूप में (कमोबेश) दिखती हैं, लेकिन वे इस तरह काम नहीं करती हैं। एक स्थानीय फ़ंक्शन में आप इसके सुपर फ़ंक्शन के स्थानीय चर का उपयोग कर सकते हैं। यह एक तरह का सेमी-ग्लोबल्स है। इनमें से कोई भी ट्रिक ऐसा कर सकती है। निकटतम c ++ 0x से लैम्ब्डा ट्रिक है, लेकिन यह क्लोजर परिभाषा समय में बाध्य है, उपयोग समय नहीं है।
आप C ++ में दूसरे के अंदर एक मुफ्त फ़ंक्शन को परिभाषित नहीं कर सकते।
मुझे C ++ 03 के लिए यहां एक समाधान पोस्ट करने दें जिसे मैं सबसे साफ संभव मानता हूं। *
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
(++) C ++ की दुनिया में मैक्रोज़ का उपयोग करना कभी भी साफ नहीं माना जाता है।
लेकिन हम मुख्य के अंदर एक समारोह की घोषणा कर सकते हैं:
int main()
{
void a();
}
हालाँकि सिंटैक्स सही है, कभी-कभी यह "मोस्ट वेस्टिंग पार्स" हो सकता है:
#include <iostream>
struct U
{
U() : val(0) {}
U(int val) : val(val) {}
int val;
};
struct V
{
V(U a, U b)
{
std::cout << "V(" << a.val << ", " << b.val << ");\n";
}
~V()
{
std::cout << "~V();\n";
}
};
int main()
{
int five = 5;
V v(U(five), U());
}
=> कोई प्रोग्राम आउटपुट नहीं।
(संकलन के बाद केवल क्लैंग चेतावनी)।