【问题标题】:Function template specialization - problems with pointers函数模板特化 - 指针问题
【发布时间】:2014-09-04 02:16:15
【问题描述】:

嗯,我试图在跨平台应用程序中处理 unicode 时抽象出 std::string/std::wstring 的烦恼。作为我创建转换“模板”的基本内容之一:

#ifdef _WIN32
    typedef std::wstring os_string_type;
#else
    typedef std::string os_string_type;
#endif

template <typename OSS_Ty, typename IN_Ty>
OSS_Ty string_convert(const IN_Ty& input);
template <> 
std::wstring string_convert<std::wstring, std::string>(const std::string& input);
template <> 
std::string string_convert<std::string, std::wstring>(const std::wstring& input);

我会使用 os_string_type 作为主要的“字符串类型”。但是输入是特定类型(const char* 或 const wchar_t* - 并且一些“特定于操作系统”的函数需要宽字符串或普通字符串。

所以对于我在模板上面创建的那些“接口”。 - 如果 os_string_type 与输入/输出要求相同,则默认模板。以及进行转换的具体模板。

这似乎奏效了。但是有一个“小”缺点:如前所述,输入是一个字符数组。来电: string_conver&lt;std::wstring&gt;(const char*) 确实调用但不是专业化。 C++ 似乎在处理自动类型转换之前首先选择函数类型。 (我猜这是无法克服的。


然后我写了另一个专业:

template <> 
std::wstring string_convert<std::wstring, char*>(const char* input); 

但是现在 Visual Studio (2010) 在编译时出现以下错误:

错误 C2912:显式特化; 'std::wstring string_convert(const char *)' 不是函数模板的特化

如何解决?

编辑: char * const 显然是错误的 - 它来自 const char* (并且仅通过阅读此处的“答案”而改变)。我希望能够允许我无法编辑数组中数据的常量字符数组。

更新代码


实际解决方案

(直接来自宋元瑶的帖子),但我将其发布在这里以供将来参考:

#ifdef _WIN32
    typedef std::wstring os_string_type;
#else
    typedef std::string os_string_type;
#endif
typedef char* char_array;
typedef const char* const_char_array;
typedef wchar_t* wchar_array;
typedef const wchar_t* const_wchar_array;

template <typename OSS_Ty, typename IN_Ty>
OSS_Ty string_convert(const IN_Ty& input);
template <> 
std::wstring string_convert<std::wstring, std::string>(const std::string& input);
template <> 
std::string string_convert<std::string, std::wstring>(const std::wstring& input);
template <> 
std::wstring string_convert<std::wstring, const_char_array>(const const_char_array& input);

【问题讨论】:

  • 我在这里看不到模板函数的意义。重载函数似乎就足够了。
  • @jarod42:返回类型(如果我要“忽略”其他地方的类型,则重载意味着 std::string -&gt; std::wstring 和 std::string -&gt; std::string 重载。如果函数只是“转换”从真正意义上说,这意味着我必须在代码中的其他位置添加特定于平台的(转换与非转换)——这是我试图阻止的。

标签: c++ string templates unicode


【解决方案1】:

参数input的声明不匹配。

改变

template <> 
std::wstring string_convert<std::wstring, char*>(char* const input);

到

template <> 
std::wstring string_convert<std::wstring, char*>(char* const & input);

顺便说一句:如果您尝试使用 clang,错误消息是明确的:

注意:候选模板被忽略:无法匹配 'std::basic_string
(char *const &)' 对 'std::wstring (char *const)'

【讨论】:

  • 好吧,我做了一个轻微的(但我想很重要)改变——但我设法正确地改变了它。 (现在为字符数组类型使用 typedef 以保持理智)
【解决方案2】:

我建议使用重载而不是添加另一个专业化:

inline std::wstring string_convert(char const *s)
{
    return string_convert<std::wstring, std::string>(s);
}

如果您的 string_convert 函数在内部使用 char 缓冲区,那么让模板版本和此版本调用相同的内部函数可能会提高效率。

注意。我不太明白你打算如何使用这个函数——通常你会有一个转换为特定类型的函数,而不是“切换”字符串的类型。

【讨论】:

  • 使用来自我希望将所有平台特定的东西删除到单独的区域。假设我在 Windows 上提供了一个“std::string”(UTF8)。然后我首先将其转换为std::wstring,然后再将其传递给win32 API。 - 以下:string_convert&lt;os_string_type&gt; (input_utf8) 但是在 UNIX 上,os_string_type 是类型化的(通过宏)到 std::string。因此,同一行将适用于两者,并转换为依赖于操作系统的字符串类型。使用函数重载(以及 wstring/string 返回的 2 个函数)意味着我每次都必须包含宏。
【解决方案3】:

我会这样做:

template <typename OSS_Ty>
OSS_Ty string_convert(const std::string& input);
template <typename OSS_Ty>
OSS_Ty string_convert(const std::wstring& input);

template <>
std::wstring string_convert(const std::string& input) { /* Do the conversion */ }
template <>
std::string string_convert(const std::wstring& input) { /* Do the conversion */ }

template <>
std::string string_convert(const std::string& input) { return input; }
template <>
std::wstring string_convert(const std::wstring& input) { return input; }

让从const char* 到std::string 的转换完成这项工作(因为const char* 不是模板参数)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 2019-03-23
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 2012-06-16
    • 2017-07-30
    相关资源
    最近更新 更多