Немного сложно распутать все это, но здесь определенно есть одна проблема. Этот код:
const wchar_t* ToWchar(string arg)
{
std::wstring widestr = std::wstring(arg.begin(), arg.end());
return widestr.c_str();
}
возвращает указатель на мертвую память. Память, на которую он возвращает указатель, освобождается при выходе из функции и widestr
выходит из области видимости. Если вы изменили это на это:
const wchar_t* ToWchar(string arg)
{
static ::std::wstring widestr;
widestr = std::wstring(arg.begin(), arg.end());
return widestr.c_str();
}
это может начать работать. Но тогда функция больше не будет входящей, и совершенно определенно не будет потокобезопасной.
Точно такая же ситуация для этой функции:
template<typename... T>
wchar_t* Message(T &&... args)
{
wchar_t message[100];
swprintf(message, 100, forward<T>(args)...);
return message;
}
message
выходит из области видимости, и вы возвращаете указатель на пространство мертвого стека. Опять же, если вы изменили функцию на это:
template<typename... T>
wchar_t* Message(T &&... args)
{
static wchar_t message[100];
swprintf(message, 100, forward<T>(args)...);
return message;
}
он, вероятно, начнет работать, но опять-таки больше не будет входящим или поточно-ориентированным.
Я бы переосмыслил способ, которым вы справляетесь с этим. Для решения этой проблемы используются гарантии C ++ относительно времени жизни временных пользователей:
#include <string>
#include <cstring>
extern void fake_logger_writemessage(wchar_t const *);
template <class T>
class WCharWrapper {
public:
WCharWrapper() = delete; // Make it unconstructable
};
template <>
class WCharWrapper<wchar_t const *> {
public:
WCharWrapper() = delete;
explicit WCharWrapper(wchar_t const *s) : s_(s) {}
operator wchar_t const *() const { return s_; }
private:
wchar_t const * const s_;
};
template <>
class WCharWrapper<::std::wstring const &> {
public:
WCharWrapper() = delete;
explicit WCharWrapper(::std::wstring const &s) : s_(s) {}
operator wchar_t const *() const { return s_.c_str(); }
private:
::std::wstring const &s_;
};
template <>
class WCharWrapper<char const *> {
public:
WCharWrapper() = delete;
explicit WCharWrapper(char const *s) : s_(s, s + ::std::strlen(s)) {}
operator wchar_t const *() const { return s_.c_str(); }
private:
::std::wstring const s_;
};
template <>
class WCharWrapper<::std::string const &> {
public:
WCharWrapper() = delete;
explicit WCharWrapper(::std::string const &s) : s_(s.begin(), s.end()) {}
operator wchar_t const *() const { return s_.c_str(); }
private:
::std::wstring const s_;
};
template <typename T>
T widen_strings(T &&arg)
{
return ::std::forward(arg);
}
WCharWrapper<char const *> widen_strings(char const *arg)
{
return WCharWrapper<char const *>(arg);
}
WCharWrapper<::std::string const &> widen_strings(::std::string const &arg)
{
return WCharWrapper<::std::string const &>(arg);
}
// Capture non-const as well, to make sure they aren't passed through unchanged.
WCharWrapper<::std::string const &> widen_strings(::std::string &arg)
{
return WCharWrapper<::std::string const &>(arg);
}
template <typename T>
T &&widen_strings(T && arg)
{
return arg;
}
template<typename... T>
wchar_t const *Message(wchar_t *out, T &&... args)
{
swprintf(out, widen_strings(::std::forward<T>(args))...);
return out;
}
template<typename... T>
void LogMessage(T &&... args)
{
wchar_t msgbuf[100];
fake_logger_writemessage(Message(msgbuf, ::std::forward<T>(args)...));
}
Эта версия, которую я поставил на Godbolt , должна работать отлично. Посмотрите на самый конец для примера того, как он используется.