gpt4 book ai didi

c++ - 覆盖 ctype

转载 作者:可可西里 更新时间:2023-11-01 17:56:27 26 4
gpt4 key购买 nike

我正在编写一个 lambda 演算解释器来娱乐和练习。我通过添加 ctype 让 iostreams 正确标记标识符将标点符号定义为空格的方面:

struct token_ctype : ctype<char> {
mask t[ table_size ];
token_ctype()
: ctype<char>( t ) {
for ( size_t tx = 0; tx < table_size; ++ tx ) {
t[tx] = isalnum( tx )? alnum : space;
}
}
};

(classic_table() 可能会更干净,但在 OS X 上不起作用!)

然后在我点击标识符时交换 facet:

locale token_loc( in.getloc(), new token_ctype );

locale const &oldloc = in.imbue( token_loc );
in.unget() >> token;
in.imbue( oldloc );

Web 上似乎很少有 lambda 演算代码。到目前为止我发现的大部分内容都是 unicode λ人物。所以我想尝试添加 Unicode 支持。

但是ctype<wchar_t>ctype<char> 完全不同.没有主表;有四种方法do_is x2,do_scan_is , 和 do_scan_not .所以我这样做了:

struct token_ctype : ctype< wchar_t > {
typedef ctype<wchar_t> base;

bool do_is( mask m, char_type c ) const {
return base::do_is(m,c)
|| (m&space) && ( base::do_is(punct,c) || c == L'λ' );
}

const char_type* do_is
(const char_type* lo, const char_type* hi, mask* vec) const {
base::do_is(lo,hi,vec);
for ( mask *vp = vec; lo != hi; ++ vp, ++ lo ) {
if ( *vp & punct || *lo == L'λ' ) *vp |= space;
}
return hi;
}

const char_type *do_scan_is
(mask m, const char_type* lo, const char_type* hi) const {
if ( m & space ) m |= punct;
hi = do_scan_is(m,lo,hi);
if ( m & space ) hi = find( lo, hi, L'λ' );
return hi;
}

const char_type *do_scan_not
(mask m, const char_type* lo, const char_type* hi) const {
if ( m & space ) {
m |= punct;
while ( * ( lo = base::do_scan_not(m,lo,hi) ) == L'λ' && lo != hi )
++ lo;
return lo;
}
return base::do_scan_not(m,lo,hi);
}
};

(为平面格式道歉;预览以不同方式转换了选项卡。)

代码不够优雅。我确实更好地表达了只有标点符号是附加空格的概念,但如果我有 classic_table,那在原文中就没问题了。 .

有没有更简单的方法来做到这一点?我真的需要所有这些重载吗? (测试显示 do_scan_not 在这里是无关紧要的,但我考虑得更广泛。)我是否首先滥用了方面?以上是否正确?实现更少的逻辑会是更好的风格吗?

最佳答案

(已经一年了,没有实质性的答案,同时我也学到了很多关于iostreams的知识……)

自定义方面专门为字符串提取运算符服务 in >> token .该运算符是根据 use_facet< ctype< wchar_t > >( in.getloc() ).is( ios::space, c ) 定义的“对于下一个可用的输入字符 c。” (§21.3.7.9) ctype::is只是 ctype::do_is 的 stub , 所以看起来 do_is就足够了。

不过,最新版本的 GCC 标准库确实实现了 operator>>scan_is 方面.问题是 do_scan_is然后作为对 do_is 的一系列调用来实现,虚拟调度和所有。头文件描述了do_scan_is作为用户优化的 Hook 。

因此,as-if 规则似乎庇护了仅提供第一个覆盖的实现。

请注意,检索掩码值的第二个覆盖是一个奇数。它可以按照第一种方式通过低效地一点一点地构建掩码来实现。在 GCC 中,它是根据系统调用实现的,每个字符调用 15 次,一点一点地构建掩码,效率低下。这似乎牺牲了性能和兼容性。幸运的是,似乎没有人使用它。


无论如何,这一切都很好,但只需使用 streambuf_iterator<wchar_t> 编写分词器即可。更简单,更具可扩展性,并简化了异常处理。

关于c++ - 覆盖 ctype<wchar_t>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2339593/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com