Is there a way to automatically convert a std::string into an MFC CString?

Hi,

On the surface of it, this question may seem utterly trivial but it isn't. It's actually an instance of an old problem: how can we make 2 libraries interact (one that uses std::string and the other that uses MFC CString).

Up to now, I have only come to "solve the issue" via small helper functions but the effect on the code's aesthestics is terrible.. thus I am looking for an elegant solution.

One idea I just came up with is that of creating a new string class which knows how to convert to either of the string types via implicit operators. I am going to work on it and will let you know...

Sample small helper function:

1
2
3
4
5
6
inline CString to_cstring(const std::string& msg)
	{
		std::wstring message = to_wstring(msg);
		CString msg_as_cstring{ message.c_str() };
		return msg_as_cstring;
	}


and this works but it pollutes all my code with "to_cstring" ....
Any ideas?

Regards,
Juan
Last edited on
I have a solution and would greatly appreciated your observations. I have created the following class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
inline namespace ISO_MFC
{
	class String
	{
		const CString		m_mfcStr;
	public:
		String( const std::string& str) 
			: m_mfcStr{ JD::to_cstring(str) }
		{}

		String(const CString& str)
			: m_mfcStr{ str }
		{}

		operator std::string() const noexcept
		{
			return JD::from_cstring(m_mfcStr);
		}
		operator CString() const noexcept
		{
			return m_mfcStr;
		}
		operator LPCTSTR() const noexcept
		{
			return m_mfcStr;
		}
	};
}


And its use is like so:

 
getGrid().SetItemText(row, Columns::Account, String(line->getAccount()));


which is better than:

1
2
auto account = JD::to_cstring(line->getAccount());
getGrid().SetItemText(row, Columns::Account,account);


because in the first code, we don't need to worry what kind of string getAccount() returns, nor which kind of string SetItemText expects in its 3rd parameter. We improve abstraction by specifying only that we get a string from getAccount() and we pass some kind of String into SetItemText, but we don't have to worry about which kind of strings actually occur in each place.

Any comments?
Juan Dent
I would suggest:
* Don't invoke the conversion explicitly. Let the compiler do it. That makes the code less coupled to the particular type being handled.
* Make ISO_MFC perform its conversions lazily.
Would be nice if that worked. I don't seem to succeed in making the conversion implicitly.

For example, the following code does not compile:

 
	getGrid().SetItemText(row, Columns::Account, line->getAccount());


Here getAccount() returns a std::string, while SetItemText is defined like so:

 
BOOL CGridCtrl::SetItemText(int,int,LPCTSTR)



The error is:


cannot convert argument 3 from 'const std::string' to 'LPCTSTR'


yet the class I defined has a ctor accepting a const std::string& and has implicit conversion operator that return a LPCTSTR!!

So, how to this without explicitly mentioning the class String (our "ambassador" between ISO and MFC library)?

It would work if the function is expected to receive a String and what was sent was a std::string or CString -- in this cases the implicit conversion would occur, like so:


1
2
3
4
5
6
7
8
9
10
11
12
void test(const String& str)  // CString --> String works
{
}
void testOther(const std::string& str)  // CString --> std::string does NOT work
{
}
void caller()
{
	CString sss;
	test(sss);   // OK
       testOther(sss);    // not Ok
}



Regards,
Juan
Last edited on
Oh, OK. I thought SetItemText() was your own function. Yeah, there's no way to make that work via implicit conversion, so never mind.
closed account (E0p9LyTq)
Is there a way to automatically convert a std::string into an MFC CString?

Yes there is, use the std::string::c_str() method as the parameter for the CString ctor.

One of CString's ctor's, CString(const unsigned char* psz), uses a null-terminated C-style string. c_str() returns a null-terminated sequence of characters, a C-style string.

Have a wide string? Use std::wstring::c_str().
Topic archived. No new replies allowed.