clang std :: isspace编译错误

时间:2018-01-16 12:17:55

标签: c++ c++11 c++14 clang++

以下代码在VS 2015(更新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.

我在这里缺少什么? 任何标题包含?如果是这样,那是哪一个? 如果没有,还有其他解决方法吗?

2 个答案:

答案 0 :(得分:5)

<locale>中的std::isspace重载相当于(按标准):

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

如您所见,这需要针对给定的std::ctype进行CharT的特化。

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

答案 1 :(得分:3)

问题是std::locale的{​​{1}}实现使用了std::ctype中定义的字符特征,它们定义了字符类型的某些特征。

不幸的是,标准只要求std::isspace专门用于std::ctypechar,而不是wchar_t。似乎MSVC和GCC正在提供额外的实现(因为它是有意义的)。 (编辑:GCC实际上会抛出异常)。

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

这给我们留下了一些选择:

  • 在使用namespace std中的char之前,将您的角色投放到wchar_tstd::isspace
    • 请注意,对于<locale>,这通常是缩小转化,您可能不希望
  • 切换为使用char std::isspace的实施方案,其中<cctype>投射到int
    • 如果类型无法在unsigned char内表示您有未定义的行为,那么这可能也不是您想要的,具体取决于您使用的类型(请查看sizeof(unsigned char)
  • 为你的角色类型编写自己的特征(可能是现在最好的选择)
  • 提交缺陷报告,希望委员会同意您的意见,然后等待两年或更长时间才能修复:-)
    • 或者要求clang作者添加这种便利(也不是一个坏主意)
  • 编写自己的专业化内容,例如@Holt,并且只是处理未定义的行为

相关:How well is Unicode supported in C++11?