我想简化代码以对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'
我对参数化函数不熟悉。
答案 0 :(得分:4)
char
和wchar_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, ...){...}