在函数中传递字符串或wstring

时间:2019-05-09 11:15:07

标签: c++

我想简化代码以对ANSI和UNICODE字符串版本使用相同的功能

tstring formatW(const std::string format, ...);
tstring formatA(const std::wstring format, ...);

在单个参数化函数中

tstring format(const tstring format, ...);

但是,如果我使用它,则会在第3行出现错误

  const std::string fmtA =  "MouseWheel nFlags %u,zDelta %d, CPoint(%d,%d";
  std::string strA  = formatA(fmtA, nFlags, zDelta, pt.x, pt.y );   // Ok
  std::string strA2 = format (fmtA, nFlags, zDelta, pt.x, pt.y );   // Fail :(

  const std::wstring fmtW = L"MouseWheel nFlags %u,zDelta %d, CPoint(%d,%d";
  std::wstring strW  = formatW(fmtW, nFlags, zDelta, pt.x, pt.y);  // Ok
  std::wstring strW2 = format (fmtW, nFlags, zDelta, pt.x, pt.y);  // Fail

我得到的错误是:

  

错误C2664:〜tstring Format(const tstring,..'。)':无法将参数1从'const std :: string'转换为'const tstring'

我对参数化函数不熟悉。

3 个答案:

答案 0 :(得分:4)

charwchar_t(字符串/ wstring的下划线类型)不兼容(8位和16位),因此无法在运行时检查环境中将它们组合在一起。

这就是为什么Windows例如具有两个版本的许多功能(MessageBoxA,MessageBoxW等)的原因。

解决方案:使用一个将数据存储为UTF-8(字符)的类,然后在需要wchar_t时将其转换为16位。或者更好,反之亦然(在内部使用wchar_t并在需要使用char *时将数据转换为UTF-8)。

答案 1 :(得分:1)

我假设您有充分的理由不只是做Microsoft #ifdef UNICODE的事情?我承认这有点垃圾。

您无法在运行时检查它们,但这正是发明c ++编译时重载的原因。

所以您可能需要做3件事:

1)编写2个函数原型,为您提供所需的行为

2)将它们转换为采用可变参数模板参数列表,而不是...

3)将所有内容封装在模板化类中。

1)要声明和实现两个具有相同名称的辅助函数,只需执行此操作即可。编译器将根据第一个参数来区分它们:

tstring format(const std::string& format, ...);
tstring format(const std::wstring& format, ...);

当然,您最终要写两次相同的样板代码,例如:

tstring format(const std::string& format, ...) {
  va_list format;         /// hmm va_list with references - may need a tweak!
  va_start(format, __arg);
  return vformatA(format, __arg);
}

对于您合并的每种方法,都很难为它编写两次。

2)要使用可变参数模板,请声明并实现以下功能:

template <typename... T>
tstring format(const std::string& format, const T& ... t)
{
  return formatA(format, t...);
}

同样,您需要编写两次。与c风格的变量相比,它并不太复杂,因此您可以接受。

3)第三个可选步骤是编写一个Helper模板类。因此,其想法是实际的实现是在helper类中执行的,而该helper类仅针对字符串和宽字符串定义。老实说,它要做的只是增加体积,并迫使您同时实现这两种方法。

答案 2 :(得分:0)

您始终可以使用模板并将模板限制为仅字符串和wstring类型,因此

template <typename T>
T format(const T format, ...);

然后再声明两个函数,这些函数将根据类型执行所需的操作,所以

std::string format<std::string>(const std::string format, ...){...}
std::wstring format<std::wstring>(const std::wstring format, ...){...}