0

I don't know how to change wstring value in struct . I don't know where is my error. do you help me ?

I can't understand why string value change success, wstring value change failed .

struct TestStruct{
  string falg1;
  wstring falg2;

  TestStruct setFlag1(string str ) {
    falg1 = str;
    return *this;
  }

  TestStruct setFlag2(wstring str ) {
    falg2 = str;
    return *this;
  }
};



int main(int argc,
         char ** argv) { 

      TestStruct testStruct;
      testStruct.setFlag1("string")
                .setFlag2(L"Wstring");
                
      wcout << "string length:" << testStruct.falg1.size() << endl;
      wcout << "Wstring content:" << '[' << testStruct.falg2 << ']' << endl;
      wcout << "Wstring length:" << '[' << testStruct.falg2.size() << ']' << endl;
}

The output content is :

string length:6
Wstring content:[]
Wstring length:[0]
Tom
  • 333
  • 2
  • 8
  • 5
    Both functions return copy of `*this` instead of reference. – user7860670 Aug 23 '22 at 10:01
  • 4
    because setFlag1 (and 2) return **a copy** of *this, so you are apply `setFlag2` to a temporary object you don't consider in cout. Change both function signatures and return a `TestSruct&` to see the difference – Gian Paolo Aug 23 '22 at 10:02
  • 2
    Why even returning an object on setFlag call? That looks totally wrong – RoQuOTriX Aug 23 '22 at 10:03

1 Answers1

0

I am not sure why are you trying to return a copy of your struct, the code looks really weird. I would use a method returning nothing and then setting the flags works as expected:

#include <string>
#include <iostream>

struct TestStruct{
  std::string falg1;
  std::wstring falg2;

  void setFlag1(std::string str ) {
    falg1 = str;
  }

  void setFlag2(std::wstring str ) {
    falg2 = str;
  }
};



int main(int argc,
         char ** argv) { 

      TestStruct testStruct;
      testStruct.setFlag1("string");
      testStruct.setFlag2(L"Wstring");
                
      std::wcout << "string length:" << testStruct.falg1.size() << std::endl;
      std::wcout << "Wstring content:" << '[' << testStruct.falg2 << ']' << std::endl;
      std::wcout << "Wstring length:" << '[' << testStruct.falg2.size() << ']' << std::endl;
}

Output:

string length:6
Wstring content:[Wstring]
Wstring length:[7]

As @Acanogua and @UnholySheep pointed out, it is also possible to return references and then chain the function calls as you tried in your example:

struct TestStruct{
  std::string falg1;
  std::wstring falg2;

  TestStruct& setFlag1(std::string str ) {
    falg1 = str;
    return *this;
  }

  TestStruct& setFlag2(std::wstring str ) {
    falg2 = str;
    return *this;
  }
};



int main(int argc,
         char ** argv) { 

      TestStruct testStruct;
      testStruct.setFlag1("string").setFlag2(L"Wstring");
                
      std::wcout << "string length:" << testStruct.falg1.size() << std::endl;
      std::wcout << "Wstring content:" << '[' << testStruct.falg2 << ']' << std::endl;
      std::wcout << "Wstring length:" << '[' << testStruct.falg2.size() << ']' << std::endl;
}
RoQuOTriX
  • 2,871
  • 14
  • 25
  • Why change it to `void` instead of `TestStruct&`? The latter requires fewer changes to the original code and does exactly what OP intended – UnholySheep Aug 23 '22 at 10:07
  • @UnholySheep but he is not using a reference, he is using a copy – RoQuOTriX Aug 23 '22 at 10:11
  • 1
    Which is the mistake in the original code. Returning a reference instead of a copy would be the correct fix. – UnholySheep Aug 23 '22 at 10:13
  • 2
    @UnholySheep I agree that the void return type is actually the more correct one. Being able to chain function calls might look convenient, but shouldn't be done here; if really both flags should be set at once I'd rather provide yet another setter. Agree with you, though, that the other variant should at least be mentioned (*'If you really insist on ... then ...'*). – Aconcagua Aug 23 '22 at 10:14
  • @UnholySheep I agree on you with that point but the intention of the author is not really clear – RoQuOTriX Aug 23 '22 at 10:14
  • 1
    @RoQuOTriX I'd consistently [avoid `using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) in answers even if that has been present in the question already... – Aconcagua Aug 23 '22 at 10:17
  • 1
    @RoQuOTriX About the intention, well, appears pretty clear to me that user intends to chain function calls for convenience in the style of e.g. `TheRealObject o; /* much code */ o.setFlag1(...).doSomethingElse().resetFlag1();` or whatever else... – Aconcagua Aug 23 '22 at 10:22
  • @Aconcagua You are totally right on that point. But as you also mentioned it shouldn't be done in that example if we consider good coding practices here – RoQuOTriX Aug 23 '22 at 10:25
  • @RoQuOTriX Well, just mentioned the *intention* without qualifying in that comment – indeed, did so earlier. And here comes in play your wording: *'it is also possible'*. This presents the alternative as *equivalent*, though it isn't. I'd chose wording more clearly expressing this issue. – Aconcagua Aug 23 '22 at 10:33
  • thanks everyone , you helped me find my boundary . – Tom Aug 23 '22 at 12:36