NEW: Thank you everyone who helped me with this! The answer is marked below, and I\'ve expanded on the answer with a functioning version in my question, below (q.v.):
This piece is my own personal tiny little bit of genius.
#include
template to* make_stack_temporary(const char(&lit)[size], to* memory = (to*)_alloca(sizeof(to)*size)) {
for(int i = 0; i < size; i++)
memory[i] = lit[i];
return memory;
}
When you use alloca in a default argument, it's actually allocated off the caller's stack, allowing you to return arrays without resorting to the heap. No dynamic allocation, no memory freeing. _alloca is a CRT function provided by MSVC, so I don't give any portability guarantees - but if you're using ATL that's likely no problem anyway. Of course, this also means that the pointer cannot be held past the calling function, but it should suffice for temporary uses like format strings. There are also some caveats to do with exception handling that you are unlikely to come across (check MSDN for details), and of course, it will only work for characters which have the same binary representation, which to my knowledge is every character you can put in a narrow string literal. I appreciate that this only solves a subset of the actual problems you may have encountered, but it's a far superior solution to that specific subset than the macro, or specifying every literal twice, etc.
You can also use the definitely uglier but more behaviourally consistent aggregate initialization.
template some_type some_func() {
static const T array[] = { 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', 'l', 'i', 't', 'e', 'r', 'a', 'l', '\0' };
}
In C++0x with variadic templates, it may be possible for this solution to not suck. I'm CLOSE to a better solution which is C++03, but don't hold your breath.
Edit: You can do this, which imo is the best solution, still involves some messing around.
#include
#include
#include
struct something {
static const char ref[];
};
const char something::ref[] = "";
template struct to_literal {
private:
static to hidden[N];
public:
to_literal()
: ref(hidden) {
for(int i = 0; i < N; i++)
hidden[i] = (*t_ref)[i];
}
const to(&ref)[N];
};
template to to_literal::hidden[];
template const to* make_literal() {
return to_literal().ref;
}
int main() {
std::wcout << make_literal();
std::wcin.get();
}
You have to go through every literal and make it a static member of a struct, then reference it, but it works much better.