सुविधाजनक सी ++ संरचना आरंभीकरण


141

मैं 'पॉड' C ++ स्ट्रक्चर्स को इनिशियलाइज़ करने का एक सुविधाजनक तरीका खोजने की कोशिश कर रहा हूँ। अब, निम्नलिखित संरचना पर विचार करें:

struct FooBar {
  int foo;
  float bar;
};
// just to make all examples work in C and C++:
typedef struct FooBar FooBar;

यदि मैं इसे C (!) में सुविधाजनक रूप से आरंभ करना चाहता हूं, तो मैं बस लिख सकता हूं:

/* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C

ध्यान दें कि मैं स्पष्ट रूप से निम्नलिखित संकेतन से बचना चाहता हूं, क्योंकि यह मुझे मेरी गर्दन को तोड़ने के लिए बनाया जा रहा है अगर मैं भविष्य में संरचना में कुछ भी बदलता हूं :

/* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style?

/* A */उदाहरण में C ++ में समान (या कम से कम समान) प्राप्त करने के लिए, मुझे एक आइडियल कंस्ट्रक्टर लागू करना होगा:

FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {}
// ->
/* C */ FooBar fb(12, 3.4);

जो उबलते पानी के लिए अच्छा है, लेकिन आलसी लोगों के लिए उपयुक्त नहीं है (आलस्य एक अच्छी बात है, ठीक है?)। इसके अलावा, यह /* B */उदाहरण के रूप में बहुत बुरा है , क्योंकि यह स्पष्ट रूप से नहीं बताता है कि कौन सा मूल्य किस सदस्य को जाता है।

तो, मेरा प्रश्न मूल रूप से है कि मैं /* A */C ++ में कुछ इसी तरह या बेहतर कैसे हासिल कर सकता हूं ? वैकल्पिक रूप से, मैं एक स्पष्टीकरण के साथ ठीक होगा कि मुझे ऐसा क्यों नहीं करना चाहिए (अर्थात मेरा मानसिक प्रतिमान खराब क्यों है)।

संपादित करें

द्वारा सुविधाजनक है, मैं भी मतलब पोषणीय और गैर-अनावश्यक


2
मुझे लगता है कि बी उदाहरण उतना ही करीब है जितना आप प्राप्त करने जा रहे हैं।
मार्लोन

2
मैं यह नहीं देखता कि B कितनी खराब शैली का उदाहरण है। यह मेरे लिए समझ में आता है, क्योंकि आप प्रत्येक सदस्य को उनके संबंधित मूल्यों के साथ आरंभ कर रहे हैं।
माइक बेली

26
माइक, यह खराब शैली है क्योंकि यह स्पष्ट नहीं है कि कौन सा मूल्य किस सदस्य को जाता है। आपको संरचना की परिभाषा को देखना होगा और फिर प्रत्येक मूल्य का अर्थ खोजने के लिए सदस्यों की गणना करना होगा।
jnnnnn

9
इसके अलावा, अगर भविष्य में फूबर की परिभाषा को बदलना है, तो आरंभिकता टूट सकती है।
एडवर्ड फॉक

यदि आरंभीकरण लंबा और जटिल हो जाता है, तो बिल्डर पैटर्न के बारे में मत भूलना
स्लेज

जवाबों:


20

नामित आरंभ को c ++ 2a में समर्थित किया जाएगा, लेकिन आपको प्रतीक्षा करने की आवश्यकता नहीं है, क्योंकि वे आधिकारिक तौर पर GCC, Clang और MSVC द्वारा समर्थित हैं ।

#include <iostream>
#include <filesystem>

struct hello_world {
    const char* hello;
    const char* world;
};

int main () 
{
    hello_world hw = {
        .hello = "hello, ",
        .world = "world!"
    };

    std::cout << hw.hello << hw.world << std::endl;
    return 0;
}

GCC Demo MSVC Demo


कैविट एम्प्टर: ध्यान रखें कि यदि आप बाद में संरचना के अंत में पैरामीटर जोड़ते हैं, तो पुरानी इनिशियलाइज़ेशन अभी भी इनिशियलाइज़ किए बिना चुपचाप संकलित हो जाएगी।
१२:१ats बजे कैटस्कुल

1
@ कैट्सकुल नं। इसे प्रारंभिक आरम्भिक सूची के साथ आरम्भ किया जाएगा, जिसके परिणामस्वरूप शून्य के साथ आरंभीकरण होगा।
.िवगुल्ट

आप सही हे। धन्यवाद। मुझे स्पष्ट करना चाहिए, शेष पैरामीटर चुपचाप प्रारंभिक रूप से डिफ़ॉल्ट रूप से प्रभावी हो जाएंगे। मेरे कहने का मतलब यह था कि किसी को भी उम्मीद है कि इससे पीओडी प्रकारों के पूर्ण स्पष्ट आरंभ को लागू करने में मदद मिलेगी, जो निराश होगा।
कैटस्कुल

43

चूंकि style AC ++ में अनुमति नहीं है और आप style Bतब नहीं चाहते कि कैसे उपयोग किया जाए style BX:

FooBar fb = { /*.foo=*/ 12, /*.bar=*/ 3.4 };  // :)

कम से कम कुछ हद तक मदद करें।


8
+1: यह वास्तव में सही संकलन (कंपाइलर POV से) सुनिश्चित नहीं करता है, लेकिन निश्चित रूप से पाठक की मदद करता है ... हालांकि टिप्पणियों को सिंक में रखा जाना चाहिए।
मैथ्यू एम।

18
टिप्पणी अगर मैं के बीच नई फ़ील्ड सम्मिलित तोड़ा जा रहा है से संरचना के प्रारंभ से नहीं रोकता है fooऔर barभविष्य में। सी अभी भी हम चाहते हैं कि खेतों को इनिशियलाइज़ करेंगे, लेकिन C ++ नहीं होगा। और यह प्रश्न का बिंदु है - C ++ में समान परिणाम कैसे प्राप्त करें। मेरा मतलब है, पायथन नामांकित तर्कों के साथ करता है, सी - "नामित" फ़ील्ड के साथ, और सी ++ में भी कुछ होना चाहिए, मुझे उम्मीद है।
dmitry_romanov

2
टिप्पणियाँ सिंक में? मुझे एक विराम दें। सुरक्षा खिड़की के माध्यम से चला जाता है। मापदंडों और उछाल को फिर से व्यवस्थित करें। के साथ बहुत बेहतर है explicit FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) स्पष्ट कीवर्ड नोट करें । सुरक्षा के संबंध में भी मानक को तोड़ना बेहतर है। क्लैंग में: -Wno-c99- एक्सटेंशन
डैनियल हे

@ डैनियलडब्ल्यू, यह बेहतर या क्या नहीं है के बारे में नहीं है। यह जवाब है कि ओपी स्टाइल ए (सी + + नहीं), बी या सी नहीं चाहता है, जो सभी वैध मामलों को कवर करता है।
आईमिलिंड

@iammilind मुझे लगता है कि ओपी का मानसिक प्रतिमान क्यों खराब है , इसका जवाब देने में सुधार किया जा सकता है। मैं इसे अब जितना खतरनाक मानता हूं।
डेरास्ट

10

आप एक लैम्ब्डा का उपयोग कर सकते हैं:

const FooBar fb = [&] {
    FooBar fb;
    fb.foo = 12;
    fb.bar = 3.4;
    return fb;
}();

इस मुहावरे की अधिक जानकारी हर्ब सटर के ब्लॉग पर पाई जा सकती है ।


1
ऐसा दृष्टिकोण खेतों को दो बार आरंभीकृत करता है। एक बार कंस्ट्रक्टर में। दूसरा है fb.XXX = YYY
Dmytro Ovdiienko

9

उन कार्यों में प्रतियोगियों को निकालें जो उनका वर्णन करते हैं (मूल रीफैक्टरिंग):

FooBar fb = { foo(), bar() };

मुझे पता है कि शैली उस व्यक्ति के बहुत करीब है जिसे आप उपयोग नहीं करना चाहते थे, लेकिन यह निरंतर मूल्यों के आसान प्रतिस्थापन को सक्षम करता है और उन्हें भी समझाता है (इस प्रकार टिप्पणियों को संपादित करने की आवश्यकता नहीं है), अगर वे कभी भी बदलते हैं।

एक और चीज जो आप कर सकते हैं (जब से आप आलसी हैं) कंस्ट्रक्टर को इनलाइन बनाना है, इसलिए आपको ज्यादा टाइप नहीं करना है ("Foobar ::" को हटाने और समय एच और सीपीपी फ़ाइल के बीच स्विच करने में):

struct FooBar {
  FooBar(int f, float b) : foo(f), bar(b) {}
  int foo;
  float bar;
};

1
मैं किसी और को इस प्रश्न को पढ़ने के लिए इस उत्तर के लिए नीचे दिए गए कोड-स्निपेट में शैली का चयन करने की सलाह देता हूं, यदि आप जो करना चाहते हैं वह मूल्यों के एक सेट के साथ संरचनाओं को जल्दी से शुरू करने में सक्षम है।
kayleeFrye_onDeck

8

आपका प्रश्न कुछ कठिन है क्योंकि फ़ंक्शन भी:

static FooBar MakeFooBar(int foo, float bar);

कहा जा सकता है:

FooBar fb = MakeFooBar(3.4, 5);

अंतर्निहित संख्यात्मक प्रकारों के लिए प्रचार और रूपांतरण नियमों के कारण। (सी वास्तव में दृढ़ता से टाइप नहीं किया गया है)

C ++ में, आप जो चाहते हैं वह प्राप्त करने योग्य है, हालांकि टेम्प्लेट और स्थिर कथनों की सहायता से:

template <typename Integer, typename Real>
FooBar MakeFooBar(Integer foo, Real bar) {
  static_assert(std::is_same<Integer, int>::value, "foo should be of type int");
  static_assert(std::is_same<Real, float>::value, "bar should be of type float");
  return { foo, bar };
}

C में, आप मापदंडों को नाम दे सकते हैं, लेकिन आप कभी भी आगे नहीं बढ़ेंगे।

दूसरी ओर, यदि आप चाहते हैं कि सभी का नाम पैरामीटर है, तो आप बहुत सारे बोझिल कोड लिखते हैं:

struct FooBarMaker {
  FooBarMaker(int f): _f(f) {}
  FooBar Bar(float b) const { return FooBar(_f, b); }
  int _f;
};

static FooBarMaker Foo(int f) { return FooBarMaker(f); }

// Usage
FooBar fb = Foo(5).Bar(3.4);

और अगर आपको पसंद है तो आप प्रमोशन प्रोटेक्शन में काली मिर्च डाल सकते हैं।


1
"C ++ में, आप जो चाहते हैं वह प्राप्त करने योग्य है": क्या ओपी मापदंडों के क्रम के मिश्रण को रोकने में मदद करने के लिए नहीं कह रहा था? आप जिस प्रस्ताव को प्रस्तावित करते हैं, वह कैसे प्राप्त होगा? बस सादगी के लिए, मान लें कि हमारे पास 2 पैरामीटर हैं, दोनों इंट।
अधिकतम

@ मोम: यह तभी रोकेगा जब प्रकार अलग-अलग होंगे (भले ही वे एक दूसरे के लिए परिवर्तनीय हों), जो ओपी स्थिति है। यदि यह प्रकारों को अलग नहीं कर सकता है, तो निश्चित रूप से यह काम नहीं करता है, लेकिन यह एक अन्य प्रश्न है।
मैथ्यू एम।

आह मिल गया। हाँ, ये दो अलग-अलग समस्याएं हैं, और मुझे लगता है कि दूसरे का फिलहाल C ++ में अच्छा समाधान नहीं है (लेकिन ऐसा प्रतीत होता है कि C ++ 20 कुल आरंभ में C99- शैली पैरामीटर नाम के लिए समर्थन जोड़ रहा है)।
अधिकतम

6

कई कंपाइलर्स C ++ फ्रंटेंड (GCC और क्लैंग सहित) C इनिशियलाइज़र सिंटैक्स को समझते हैं। यदि आप कर सकते हैं, तो बस उस विधि का उपयोग करें।


16
जो C ++ मानक के अनुरूप नहीं है!
बिटमैस्क

5
मुझे पता है कि यह गैर-मानक है। लेकिन अगर आप इसका उपयोग कर सकते हैं, तो यह अभी भी एक संरचना को शुरू करने का सबसे समझदार तरीका है।
मथायस उरलिचस

2
आप गलत प्रकार के एक्स और वाई बनाने वाले निजी कंस्ट्रक्टर की रक्षा कर सकते हैं:private: FooBar(float x, int y) {};
dmitry_romanov

4
clang (llvm आधारित c ++ कंपाइलर) भी इस सिंटैक्स का समर्थन करता है। बहुत बुरा यह मानक का हिस्सा नहीं है।
nimrodm

हम सभी जानते हैं कि सी इनिशियलाइज़र C ++ मानक का हिस्सा नहीं हैं। लेकिन कई कंपाइलर इसे समझते हैं और सवाल यह नहीं कहता कि कौन सा कंपाइलर लक्षित हो रहा है, यदि कोई हो। इस प्रकार कृपया इस उत्तर को न दें।
मथियास उरलिचस

4

फिर भी C ++ में एक और तरीका है

struct Point
{
private:

 int x;
 int y;

public:
    Point& setX(int xIn) { x = Xin; return *this;}
    Point& setY(int yIn) { y = Yin; return *this;}

}

Point pt;
pt.setX(20).setY(20);

2
कार्यात्मक प्रोग्रामिंग के लिए बोझिल (यानी एक फ़ंक्शन कॉल की तर्क सूची में ऑब्जेक्ट का निर्माण करना), लेकिन वास्तव में एक स्वच्छ विचार अन्यथा!
बिटमैस्क

27
आशावादी शायद इसे कम कर देता है, लेकिन मेरी आँखें नहीं है।
मैथ्यू एम।

6
दो शब्द: अर्घ ... अर्घ! 'पॉइंट पीटी' के साथ सार्वजनिक डेटा का उपयोग करने से यह कैसे बेहतर है; pt.x = pt.y = 20;? या यदि आप इनकैप्सुलेशन चाहते हैं, तो यह एक कंस्ट्रक्टर से बेहतर कैसे है?
ओल्डपेकुलियर

3
यह एक कंस्ट्रक्टर से बेहतर है क्योंकि आपको पैरामीटर ऑर्डर के लिए कंस्ट्रक्टर डिक्लेरेशन को देखना होगा ... क्या यह x, y या y, x है, लेकिन जिस तरह से मैंने इसे दिखाया है वह कॉल साइट पर स्पष्ट है
parapura rajkumar

2
यदि आप एक कॉस्ट स्ट्रक्चर चाहते हैं तो यह काम नहीं करता है। या यदि आप संकलक से कहना चाहते हैं कि वह असिंचित संरचना की अनुमति न दे। यदि आप वास्तव में इसे इस तरह से करना चाहते हैं, तो कम से कम बसने वालों को चिह्नित करें inline!
मथायस उरलिच

3

विकल्प D:

FooBar FooBarMake(int foo, float bar)

कानूनी सी, कानूनी सी ++। POD के लिए आसानी से अनुकूलन योग्य है। बेशक कोई नामित तर्क नहीं हैं, लेकिन यह सभी सी ++ की तरह है। यदि आप नामांकित तर्क चाहते हैं, तो उद्देश्य C बेहतर विकल्प होना चाहिए।

विकल्प ई:

FooBar fb;
memset(&fb, 0, sizeof(FooBar));
fb.foo = 4;
fb.bar = 15.5f;

कानूनी सी, कानूनी सी ++। नामित तर्क।


12
FooBar fb = {};C ++ में उपयोग किए जा सकने वाले मेमसेट के बजाय , यह सभी स्ट्रक्चर सदस्यों को डिफ़ॉल्ट-इनिशियलाइज़ करता है।
ö तिएब

@ ,ÖTiib: दुर्भाग्य से यह अवैध सी है, हालांकि।
सीबी बेली

3

मुझे पता है कि यह प्रश्न पुराना है, लेकिन इसे हल करने का एक तरीका है जब तक कि C ++ 20 अंत में C से C ++ तक यह सुविधा नहीं लाता है। आप इसे हल करने के लिए क्या कर सकते हैं अपने इनिशियलाइज़ेशन को मान्य करने के लिए static_asserts के साथ प्रीप्रोसेसर मैक्रोज़ का उपयोग करें। (मुझे पता है कि मैक्रोज़ आम तौर पर खराब होते हैं, लेकिन यहां मुझे दूसरा रास्ता नहीं दिखता।) नीचे उदाहरण कोड देखें:

#define INVALID_STRUCT_ERROR "Instantiation of struct failed: Type, order or number of attributes is wrong."

#define CREATE_STRUCT_1(type, identifier, m_1, p_1) \
{ p_1 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_2(type, identifier, m_1, p_1, m_2, p_2) \
{ p_1, p_2 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\

#define CREATE_STRUCT_4(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3, m_4, p_4) \
{ p_1, p_2, p_3, p_4 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_4) >= (offsetof(type, m_3) + sizeof(identifier.m_3)), INVALID_STRUCT_ERROR);\

// Create more macros for structs with more attributes...

तब जब आपके पास कास्ट विशेषताओं के साथ एक संरचना होती है, तो आप यह कर सकते हैं:

struct MyStruct
{
    const int attr1;
    const float attr2;
    const double attr3;
};

const MyStruct test = CREATE_STRUCT_3(MyStruct, test, attr1, 1, attr2, 2.f, attr3, 3.);

यह थोड़ा असुविधाजनक है, क्योंकि आपको हर संभव संख्या के लिए मैक्रोज़ की आवश्यकता है और आपको मैक्रो कॉल में अपने उदाहरण के प्रकार और नाम को दोहराने की आवश्यकता है। इसके अलावा, आप मैक्रो का उपयोग रिटर्न स्टेटमेंट में नहीं कर सकते हैं, क्योंकि आरंभीकरण आरम्भ होने के बाद आता है।

लेकिन यह आपकी समस्या को हल करता है: जब आप संरचना बदलते हैं, तो संकलन-समय पर कॉल विफल हो जाएगी।

यदि आप C ++ 17 का उपयोग करते हैं, तो आप इन मैक्रों को समान प्रकारों के लिए बाध्य करके और भी सख्त बना सकते हैं, जैसे:

#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_1) == typeid(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_2) == typeid(identifier.m_2), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_3) == typeid(identifier.m_3), INVALID_STRUCT_ERROR);\

नामित आरमियों को अनुमति देने के लिए C ++ 20 का प्रस्ताव है?
मैटल नाइसन


2

जिस तरह /* B */से सी ++ में ठीक है, सी ++ 0x भी सिंटैक्स का विस्तार करने जा रहा है, इसलिए यह सी ++ कंटेनरों के लिए भी उपयोगी है। मुझे समझ में नहीं आता कि आप इसे खराब शैली क्यों कहते हैं?

यदि आप नाम के साथ मापदंडों को इंगित करना चाहते हैं तो आप बूस्ट पैरामीटर लाइब्रेरी का उपयोग कर सकते हैं , लेकिन यह किसी अपरिचित को भ्रमित कर सकता है।

संरचनात्मक सदस्यों को फिर से व्यवस्थित करना फ़ंक्शन मापदंडों को पुन: क्रमबद्ध करने जैसा है, यदि आप इसे बहुत सावधानी से नहीं करते हैं, तो ऐसी रिफैक्टरिंग समस्याएं पैदा कर सकती हैं।


7
मैं इसे खराब शैली कहता हूं क्योंकि मुझे लगता है कि यह शून्य बनाए रखने योग्य है। यदि मैं एक और सदस्य एक वर्ष में जोड़ दूं तो क्या होगा? या यदि मैं सदस्यों के आदेश / प्रकार बदलूं? कोड को शुरू करने का हर टुकड़ा (बहुत संभावना) टूट सकता है।
बिटमैस्क

2
@bitmask लेकिन जब तक आपके पास तर्कों का नाम नहीं है, आपको कंस्ट्रक्टर कॉल को भी अपडेट करना होगा, और मुझे नहीं लगता है कि बहुत से लोग सोचते हैं कि निर्माता अचूक खराब शैली हैं। मुझे यह भी लगता है कि आरंभीकरण नाम सी नहीं है, लेकिन C99, जिनमें से C ++ निश्चित रूप से सुपरसेट नहीं है।
क्रिश्चियन राऊ

2
यदि आप संरचना को समाप्त करने के लिए एक वर्ष में एक और सदस्य जोड़ते हैं तो यह पहले से मौजूद कोड में डिफ़ॉल्ट-आरंभिक होगा। यदि आप उन्हें पुनः व्यवस्थित करते हैं तो आपको सभी मौजूदा कोड को संपादित करना होगा, कुछ नहीं करना है।
ö तिएब

1
@bitmask: पहला उदाहरण "अनमनी" होने के बाद भी होगा। यदि आप इसके बजाय संरचना में एक चर का नाम बदलते हैं तो क्या होता है? ज़रूर, आप एक जगह-सब कर सकते हैं, लेकिन यह गलती से एक चर का नाम बदल सकता है जिसे नाम नहीं दिया जाना चाहिए।
माइक बेली

@ChristianRau कब से C99 C नहीं है? क्या C समूह और C99 एक विशेष संस्करण / ISO विनिर्देशन नहीं है?
19 वें

1

इस वाक्य रचना के बारे में क्या?

typedef struct
{
    int a;
    short b;
}
ABCD;

ABCD abc = { abc.a = 5, abc.b = 7 };

बस एक Microsoft Visual C ++ 2015 और g ++ 6.0.2 पर परीक्षण किया गया। काम करना ठीक है।
आप एक विशिष्ट मैक्रो भी बना सकते हैं, यदि आप वैरिएबल नाम को डुप्लिकेट करने से बचना चाहते हैं।


clang++3.5.0-10 -Weverything -std=c++1zइसकी पुष्टि करता है। लेकिन यह सही नहीं लगता। क्या आप जानते हैं कि मानक कहाँ पुष्टि करता है कि यह वैध C ++ है?
bitmask

मुझे नहीं पता, लेकिन मैंने बहुत समय पहले से विभिन्न कंपाइलरों में इसका इस्तेमाल किया है और कोई समस्या नहीं देखी है। अब g ++ 4.4.7 पर परीक्षण किया गया - ठीक काम करता है।
सीएलएस

5
मुझे नहीं लगता कि यह काम है। कोशिश करो ABCD abc = { abc.b = 7, abc.a = 5 };
रायमई 97

@deselect, यह काम करता है क्योंकि फ़ील्ड को मूल्य के साथ आरंभीकृत किया जाता है, ऑपरेटर द्वारा लौटाया जाता है =। तो, वास्तव में आप दो बार वर्ग के सदस्य को इनिशियलाइज़ करते हैं।
Dmytro Ovdiienko

1

मेरे लिए इनलाइजेशन को अनुमति देने का सबसे आसान तरीका इस मैक्रो का उपयोग करना है।

#define METHOD_MEMBER(TYPE, NAME, CLASS) \
CLASS &set_ ## NAME(const TYPE &_val) { NAME = _val; return *this; } \
TYPE NAME;

struct foo {
    METHOD_MEMBER(string, attr1, foo)
    METHOD_MEMBER(int, attr2, foo)
    METHOD_MEMBER(double, attr3, foo)
};

// inline usage
foo test = foo().set_attr1("hi").set_attr2(22).set_attr3(3.14);

वह मैक्रो विशेषता और आत्म संदर्भ विधि बनाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.