【问题标题】:clang std::isspace compilation errorclang std::isspace 编译错误
【发布时间】:2018-01-16 12:17:55
【问题描述】:

以下代码在 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.

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

【问题讨论】:

  • 在header中定义 --> int isspace( int ch ),这个函数只接受一个参数
  • @FrankS101 OP 正在使用locale 中定义的重载。
  • 我认为唯一的“已定义”解决方案是为其编写自己的特征,因为它尚未定义。可能是库缺陷,但值得商榷。

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


【解决方案1】:

&lt;locale&gt; 中的 std::isspace 重载等效于(根据标准):

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

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

标准只提供std::ctype&lt;char&gt;std::ctype&lt;wchar_t&gt;。由于char16_t 是一个内置类型,你不能专门化std::ctype&lt;char16_t&gt; 所以我认为你在这里搞砸了。

【讨论】:

  • 不幸的是,我认为在 std 命名空间中为内置类型提供模板特化在技术上是未定义的行为
  • @AndyG 你说得对,那么这是标准中的一个缺陷,除非我遗漏了什么。
【解决方案2】:

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

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

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

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

  • 在使用来自&lt;locale&gt;std::isspace 之前,将您的角色转换为charwchar_t
    • 请注意,对于char,这通常是一个缩小范围,您可能不希望这样做
  • &lt;cctype&gt; 转换为使用std::isspace 的实现,它转换为int
    • 如果该类型无法在 unsigned char 中表示,则您的行为未定义,因此这也可能不是您想要的,具体取决于您使用的类型(检查 sizeof(unsigned char)
  • 为你的角色类型写下你自己的特质(可能是目前最好的选择)
  • 提交缺陷报告,希望委员会同意您的意见,然后等待两年或更长时间才能修复 :-)
    • 或者让 clang 编写者添加这种便利(也不错)
  • @Holt 那样编写您自己的专业,并忍受未定义的行为

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 2013-09-27
    • 2013-08-20
    • 2015-05-08
    • 1970-01-01
    • 2015-12-25
    相关资源
    最近更新 更多