如何在处理std::字符串和c样式字符串时使用Templates

How to use Templates when working with std::strings and c-style strings?

本文关键字:字符串 样式 Templates 处理 std      更新时间:2023-10-16

当我尝试这样做时,我只是在摆弄模板:

template<typename T> void print_error(T msg)
{
#ifdef PLATFORM_WIN32
    ::MessageBox(0, reinterpret_cast< LPCSTR >(msg), "Error", MB_ICONERROR|MB_OK);
#else
    cout << msg << endl;
#endif /* PLATFORM_WIN32 */
}

当然,如果将std::string传递为T,这显然是不起作用的。因为字符串不能强制转换为char*,但是这个函数的编码方式可以允许我传递c样式的char*数组和c++std::string作为参数,并将它们转换为LPCSTR吗?

您可以使用函数重载:

void print_error(char const* msg);
void print_error(std::string const& msg);
...

这将起作用:

#include <sstream>
template<typename T> void print_error(T msg)
{
    std::ostringstream s;
    s << msg;
#ifdef PLATFORM_WIN32
    ::MessageBox(0, s.str().c_str(), "Error", MB_ICONERROR|MB_OK);
#else
    cout << s.str() << endl;
#endif /* PLATFORM_WIN32 */
}

有几种方法可以实现这一点。一种是将模板化函数与函数重载相结合:

template<typename T>
void print_error(T msg)
{
   ::MessageBox(0, reinterpret_cast< LPCSTR >(msg), "Error", MB_ICONERROR|MB_OK);
   cout << msg << endl;
}
void print_error(const std::string& msg)
{
   ::MessageBox(0, reinterpret_cast< LPCSTR >(msg.c_str()), "Error", MB_ICONERROR|MB_OK);
   cout << msg << endl;
}
int main()
{
string test = "test";
print_error(test);
print_error("test");
return 0;
}

另一种方法是部分专门化类模板(函数模板不能部分专门化)来处理标记的模板参数,该参数告诉它的值是std::string:

template <typename T>
class StringArgument{};
template <typename T>
struct ErrorPrinter
{
static void print_error(T msg)
{
   ::MessageBox(0, reinterpret_cast< LPCSTR >(msg), "Error", MB_ICONERROR|MB_OK);
}
};
template <typename T>
struct ErrorPrinter<StringArgument<T> >
{
static void print_error(T msg)
{
   ::MessageBox(0, reinterpret_cast< LPCSTR >(msg.c_str()), "Error", MB_ICONERROR|MB_OK);
}
};
int main()
{
string test = "test";   
ErrorPrinter<const char*>::print_error("sdfsdfsdf");
ErrorPrinter<StringArgument<string> >::print_error(test);
return 0;
}

为了稍微详细说明hmjd提供的解决方案,该解决方案应该适用于任何字符串输入,以及整数等。它还应该与在窗口上激活的unicode一起工作。

#include <sstream>
template<typename T> void print_error(T msg)
{
#ifdef PLATFORM_WIN32
    std::basic_ostringstream< TCHAR > ss;
    ss << msg;
    ::MessageBox(0, ss.str().c_str(), "Error", MB_ICONERROR|MB_OK);
#else
    cout << msg << endl;
#endif /* PLATFORM_WIN32 */
}

如果T是char*,您可以启用print_error,否则它将是编译时错误,即(您需要包括type_traits和c++11):

template<typename T> 
typename std::enable_if< std::is_same<T, char*>::value, void>::type print_error(T msg)
{
    ::MessageBox(0, reinterpret_cast< LPCSTR >(msg), "Error", MB_ICONERROR|MB_OK);
    cout << msg << endl;
}