I have what I want in terms of functionality (I can pass a string or wstring and the function template quotes the string or wstring with the appropriate quote_char). However, I don't like the style of my solution, I am sure there must be a more elegant approach.
prog.cc:8:36: error: constexpr variable 'quote_char' must be initialized by a constant expression
static constexpr Element const * quote_char = reinterpret_cast<Element const *>( chars[sizeof(Element) - 1]);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:15:62: note: in instantiation of static data member 'get_quote<char>::quote_char' requested here
constexpr Element const* quoted_char = get_quote<Element>::quote_char;
^
prog.cc:25:18: note: in instantiation of function template specialization 'quote<char>' requested here
std::cout << quote(std::string("abc")) << '\n';
^
prog.cc:8:49: note: reinterpret_cast is not allowed in a constant expression
static constexpr Element const * quote_char = reinterpret_cast<Element const *>( chars[sizeof(Element) - 1]);
Second, your quote_char is not a char, it's a string. Let's do chars, here's some old-school template specialization for you:
but it does compile (at least in VC 2017 v 15.3.0).
And quote_char is neither a string nor a character: it is a pointer to a char[] or wchar[].
I like to use TMP and after looking at other solutions (those posted here) I kind of like mine best.
But I was looking for a TMP solution that is better than mine: better in this sense (cleaner, more efficient, ...)
define "cleaner"? if anything, the use of reintepret_cast, pointer to void, and assumption that sizeof(wchar_t)==2 (only true on Windows because it's stuck in 1995) don't strike me as "clean". And the unnecessary string literals sitting in static memory.