TEXT like behavior of the function?

I have a lengthy function that is bloated because there doesn't seem to be a way to assign generic string with string literal on same line.

example:
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
29
#include <type_traits>
#include <string>

template<typename StringType>
StringType test()
{
	// Assign local immediately with string literal!
	StringType local; // = ?

	// This is current implementation that is not desired
        // because it results in twice as much lines
	if constexpr (std::is_base_of_v<std::basic_string<wchar_t>, StringType>)
	{
		local = L"wide string";
	}
	else
	{
                // This is where bloated portion begins...
		local = "ansi string";
	}

	return local;
}

int main()
{
	auto result = test<std::wstring>();
	return 0;
}


For example I wan to say:

StringType local = "test string"; // or L"test string"

However this won't work if StringType is wide string, on another side if I prepend L then it won't work for ANSI string.

Note that this has nothing to do with compilation mode, ex whether UNICODE is defined, this function is called for both types of strings and I need to determine how to reduce reduce code by factor of 2.

Therefore macro isn't a solution, but rather some constexpr lambda or something.
What would be the most efficient method?

Last edited on
interesting -- I found several ways to do it that add a great deal more bloat, and absolutely nothing that was honestly shorter (you can make it slightly shorter and uglier, but not do less work or any cleaner).
Yeah, I was googling out as well and realized there is indeed no way.

What is possible is to make a string conversion function and then conditionally call it for wide strings.
This would remove bloat but it would also incur linear performance penalty, ex. depending on how many strings needs to be processed.

The use of macros could probably remove the need to repeat the string content.
Perhaps something along these lines...

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
29
30
31
32
33
34
35
36
37
38
39
#include <type_traits>
#include <iostream>
#include <string>

template<typename T>
constexpr auto get_str([[maybe_unused]] const char* cstr, [[maybe_unused]] const wchar_t* wcstr)
{
	if constexpr (std::is_same_v<T, char>)
	{
		return cstr;
	}
	
	if constexpr (std::is_same_v<T, wchar_t>)
	{
		return wcstr;
	}
}

#define ASSIGN_STR(str_variable, str_literal) (str_variable = get_str<typename decltype(str_variable)::value_type>(str_literal, L ## str_literal))

template<typename StringType>
StringType test()
{
	StringType local;
	
	ASSIGN_STR(local, "test string");
	
	return local;
}


int main()
{
	auto s1 = test<std::string>();
	std::cout << s1 << "\n";
	
	auto s2 = test<std::wstring>();
	std::wcout << s2 << L"\n";
}


EDIT: renamed some variables because a std::string named "c_str" was too confusing.
Last edited on
Awesome solution and no performance penalty, I like it!
Macros again show their indispensable power.

Thank you a lot for this solution.

**EDIT:**

Due to how I'm going to use this, I made a slight modification which allows assignment inline where needed ex:

1
2
3
4
5
6
7
8
9
10
#define ASSIGN_STR(StringType, str_literal) get_str<typename StringType::value_type>(str_literal, L ## str_literal)

template<typename StringType>
StringType test()
{
        // there are many local's in function's block therefore this:
	StringType local = ASSIGN_STR(StringType, "test string");

	return local;
}
Last edited on
Topic archived. No new replies allowed.