Clang std::isspace 编译错误

clang std::isspace compilation error

本文关键字:错误 编译 isspace Clang std      更新时间:2023-10-16

以下代码在VS 2015(Update 3)和gcc 6.3(C++14)上编译良好,没有任何问题。

#include <string>
#include <locale>
int main()
{
std::u16string ustr = u"Android";
bool var = std::isspace(ustr[0],std::locale());
return 0;
}

但是,在 clang/Xcode 上,它失败并显示以下错误

Error(s):
source_file.cpp:8:10: warning: unused variable 'var' [-Wunused-variable]
bool var = std::isspace(ustr[0],std::locale());
^
In file included from source_file.cpp:2:
In file included from /usr/include/c++/v1/locale:182:
/usr/include/c++/v1/__locale:705:44: error: implicit instantiation of undefined template 'std::__1::ctype<char16_t>'
return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
^
source_file.cpp:8:21: note: in instantiation of function template specialization 'std::__1::isspace<char16_t>' requested here
bool var = std::isspace(ustr[0],std::locale());
^
/usr/include/c++/v1/__locale:427:53: note: template is declared here
template <class _CharT> class _LIBCPP_TYPE_VIS_ONLY ctype;
^
/usr/include/c++/v1/__locale:186:54: error: implicit instantiation of undefined template 'std::__1::ctype<char16_t>'
return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
^
/usr/include/c++/v1/__locale:705:12: note: in instantiation of function template specialization 'std::__1::use_facet<std::__1::ctype<char16_t> >' requested here
return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
^
source_file.cpp:8:21: note: in instantiation of function template specialization 'std::__1::isspace<char16_t>' requested here
bool var = std::isspace(ustr[0],std::locale());
^
/usr/include/c++/v1/__locale:427:53: note: template is declared here
template <class _CharT> class _LIBCPP_TYPE_VIS_ONLY ctype;
^
1 warning and 2 errors generated.

我在这里错过了什么? 任何标题包含?如果是这样,是哪一个? 如果没有,还有其他解决方法可以解决此问题吗?

<locale>中的std::isspace重载等效于(根据标准):

std::use_facet< std::ctype<charT> >(loc).is(ctype_base::space, c)

如您所见,这需要对给定CharT进行std::ctype专业化。

该标准仅提供std::ctype<char>std::ctype<wchar_t>。由于char16_t是内置类型,因此您无法专门std::ctype<char16_t>因此我认为您在这里搞砸了。

问题是std::isspacestd::locale实现使用了std::ctype中定义的字符特征,这些特征定义了字符类型的某些特征。

不幸的是,该标准只要求std::ctype专门用于charwchar_t,而不是像您需要的那样char16_t。MSVC和GCC似乎提供了额外的实现(因为它是有意义的)。(编辑:GCC实际上抛出了一个异常)。

我们不能为它添加我们自己的特化,因为 [namespace.std] 声明我们只能将用户定义类型的特化添加到namespace std.

这给我们留下了几个选择:

  • <locale>中使用std::isspace之前,将您的角色投射到charwchar_t
    • 请注意,对于char来说,这通常是您可能不希望的缩小转换
    • 范围
  • 切换到使用std::isspace的实现 从<cctype>转换为int
    • 如果类型无法在unsigned char中表示,则您有未定义的行为,因此这也可能不是您想要的,具体取决于您使用的类型(检查sizeof(unsigned char))
  • 为您的角色类型编写自己的特征(可能是目前的最佳选择)
  • 提交缺陷报告,希望委员会同意你的看法,然后等待两年或更长时间才能修复:-)
    • 或者要求Clang作家添加这种便利(也不是一个坏主意)
  • @Holt一样编写自己的专业化,只是忍受未定义的行为

相关:C++11 对 Unicode 的支持程度如何?