繁体   English   中英

从ANSI字符串转换为std :: basic_string的正确函数声明<TCHAR>

[英]A proper function declaration for conversion from ANSI string to std::basic_string<TCHAR>

我试图声明一个将const char *转换为std :: basic_string的函数,方法如下:

#include <string>
#include <cstring>

#ifdef _MSC_VER
#include <tchar.h>
#else
#define TCHAR char
#endif

typedef TCHAR Char;

typedef std::basic_string<Char> String;

template <typename = typename std::enable_if< !std::is_same<Char, char>::value >::type >
inline String FromACString(const char * p_src)
{
    String dest(std::strlen(p_src), ' ');

    auto p_cur = p_src;

    for (auto & ch : dest)
    {
        ch = *p_cur++;
    }

    return dest;
}

template <typename = typename std::enable_if< std::is_same<Char, char>::value >::type >
inline String FromACString(const char * p_src)
{
    return p_src;
}

但是出现了编译器错误。 我的想法是要有两个重载,并根据TCHAR类型启用其中一个重载。 正确的方法是什么?

VC2017的错误是:

error C2995: 'String FromACString(const char *)': function template has already been defined

Miles回答了您的enable_if什么问题。 但是,可以通过使用if constexpr来避免enable_if的细微差别:

inline std::basic_string<TCHAR>
FromACString(const char * p_src)
{
    if constexpr (std::is_same_v<TCHAR, char>) {
        // logic for case where TCHAR is char
    } else {
        // logic for case where TCHAR isn't char
    }
}

PS。 您将TCHAR转换为wchar_t (我认为这是除char之外唯一可能的其他类型),应该考虑字符编码。 您可以使用mbsrtowcs

您的代码有两个问题:

  1. SFINAE仅在相关上下文中工作。 由于typename std::enable_if<!std::is_same<Char, char>::value>::type中的任何内容都不依赖于任何模板参数,因此SFINAE不适用,并且由于std::enable_if<false>::type而导致硬错误std::enable_if<false>::type无效。
  2. 确定模板的“唯一性”时,仅考虑参数类型本身,而不考虑其默认值。 您具有功能模板template <typename> String FromACString(const char*)两个定义,这是一个错误。

要解决第一个问题,您可以引入另一个模板参数,其默认值为Char 解决第二个问题的通常方法是使用enable_if表达式本身作为模板参数类型,而不是默认值。 剩下的就是这样:

template <typename C = Char,
          std::enable_if_t<!std::is_same<C, char>::value>* = nullptr>
String FromACString(const char* p_src) {
    //...
}

template <typename C = Char,
          std::enable_if_t<std::is_same<C, char>::value>* = nullptr>
String FromACString(const char* p_src) {
    //...
}

现场演示

现在,根据Char的定义方式,最终得到一个带有签名的模板

template <typename, void*>
String FromACString(const char*);

另一个格式错误,因此被SFINAE禁用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM