什么时候前缀L对char或wchar_t literal很重要?

时间:2018-02-06 04:15:19

标签: c++

大多数情况下,我忘记了wchar_t文字的L前缀,或者我错误地将其放入char字面,似乎编译(g ++)并没有抱怨(没有错误,没有警告)我的计划按预期行事。

例如

char cString[] = "Hello World!";
*std::strchr(cString, L'W') = L'w';
std::cout << cString << std::endl;

wchar_t cWideString[] = L"Hello World!";
*std::wcschr(cWideString, 'W') = 'w';
std::wcout << cWideString << std::endl;

都工作。

这是因为,在这种情况下,&#39; W&#39;和&#39; w&#39;是单字节字符?

我很感兴趣,因为我想故意使用它,用于以下功能:

template<typename T> T* findNextSpace(T* str);

旨在用于T等于charconst charwchar_tconst wchar_t。对于任何字符类型T?

,在这种函数的定义中使用' '是否安全?

或者我应该使用类似(T)的内容来将文字转换为正确的类型?

编辑:我知道它对char*wchar_t*有所不同,但我的问题不是关于字符串文字,而是关于字符文字。

1 个答案:

答案 0 :(得分:0)

这两种情况都属于隐式转换的规则。特别是整数转换的规则。对于所有情况as wchar_t is at least as wide as a char,应明确定义charwhar_t的隐式转换。如果wchar_t的值为(或者如果值不是&#39;},则编译器可能会警告您从charwchar_t的转换中数据丢失的风险。在编译时知道,在char可表示的范围之外。

根据我的理解,整数转换规则适用于整数类型的prvalue表达式,字符是整数类型,文字(字符串文字除外)是prvalues,所以这就是为什么你看到你用字符文字看到的行为,虽然你没有用字符串文字看到它。

I don't have a version of the standard that I can look things up in, but I understand that cppreference is found to be a reasonable source of information。希望它是准确的,我正确地解释了规则。

至于你关于寻找下一个空间的问题,你应该把它分成一个单独的问题。有了这个说你应该使用std::isspace / std::iswspace(除非你特别只想要' '),然后让编译器根据T选择合适的函数:

#include <type_traits>
#include <cwctype>
#include <cctype>

template <class T>
T* findNextSpace(T* str) {
    if constexpr(std::is_same_v<T, char>) {
        //Use std::isspace
    }
    else if(std::is_same_v<T, wchar_t>) {
        //Use std::iswspace
    }
    else {
        static_assert("Not implemented");
    }
}

如果您的编译器不支持此处使用的功能,您可以使用模板专业化实现类似的解决方案:

#include <cwctype>
#include <cctype>

template <class T>
struct isspace_helper;

template <>
struct isspace_helper<char> {
    bool operator()(char c) const {
        return std::isspace(c);
    }
};

template <>
struct isspace_helper<wchar_t> {
    bool operator()(wchar_t c) const {
        return std::iswspace(c);
    }
};

显然你也可以在std::string上使用它(因为大多数人会建议您使用std::string而不是char / wchar_t数组,除非你有充分的理由不要):

#include <algorithm>
#include <string>

template <class CharT, class Traits, class Alloc>
auto findNextSpace(std::basic_string<CharT, Traits, Alloc>& str) {
    return std::find(str.begin(), str.end(), isspace_helper<CharT>{});
}

如果您的编译器不支持auto,您可以改为编写std::basic_string<CharT, Traits, Alloc>::iterator。然后可能提供一个超载,接受const的字符串 - 参考以获得良好的衡量标准。