#include <iostream>
#include <locale>
#include <string>

std::wstring
to_wide_string (std::string const& str,
		std::locale        locale)
{
  typedef std::codecvt<wchar_t, char, mbstate_t> codecvt_type;
  codecvt_type const& cvt = std::use_facet<codecvt_type>(locale);
  mbstate_t state;
  const char *cbegin = str.data(), *cend = str.data() + str.size(), *cnext;
  wchar_t *wcnext;
  wchar_t wcbuf[80];
  std::wstring ret;

  while (1)
    {
      std::codecvt_base::result res =
	cvt.in(state,
	       cbegin, cend, cnext,
	       wcbuf, wcbuf + (sizeof(wcbuf) / sizeof(wcbuf[0])), wcnext);

      if (res == std::codecvt_base::ok || std::codecvt_base::partial)
	{
	  std::cout << "1" << std::endl;
	  ret += std::wstring(wcbuf, wcnext);
	  if (cend == cnext)
	    break;
	}
      else if (res == std::codecvt_base::noconv)
	{
	  std::cout << "2" << std::endl;
	  ret += std::wstring(cbegin, cend);
	  break;
	}
      else if (res == std::codecvt_base::error)
	{
	  std::cout << "3" << std::endl;
	  break;
	}
      else
	break;

      std::cout << "4" << std::endl;
      cbegin = cnext;
    }

  return ret;
}

int main()
{
  std::locale::global(std::locale(""));
  std::cout.imbue(std::locale());
  std::wcerr.imbue(std::locale());

  std::string foo = "fffäß»";
  std::wstring wfoo = to_wide_string(foo, std::wcerr.getloc());

  std::cout << foo;
  std::wcerr << wfoo;

  return 0;
}
