计算子字符串 - 修复编译器警告

问题描述 投票:0回答:1

count_occurences
代码查找字符串中位置
c
(包含)和
start
(排除)之间字符
end
出现的次数。例如。下面的代码计算
,
中的
,b,
a,b,c
1
4
的子串),即
2

#include <iostream>
#include <algorithm>

size_t count_occurences(const std::string& str, char c, size_t start, size_t end) {
    return std::count(str.begin() + start, str.begin() + end, c);
}

int main() {
    std::string str = "a,b,c";
    size_t start = 1, end = 4;
    std::cout << count_occurences(str, ',', start, end);
    return 0;
}

使用

clang++ -Wconversion
编译时,我收到以下警告:

a.cpp:5:12: warning: implicit conversion changes signedness: '_Iter_diff_t<_String_const_iterator<_String_val<_Simple_types<char>>>>' (aka 'long long') to 'size_t' (aka 'unsigned long long') [-Wsign-conversion]
    5 |     return std::count(str.begin() + start, str.begin() + end, c);
      |     ~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cpp:5:58: warning: implicit conversion changes signedness: 'size_t' (aka 'unsigned long long') to 'difference_type' (aka 'long long') [-Wsign-conversion]
    5 |     return std::count(str.begin() + start, str.begin() + end, c);
      |                                                        ~ ^~~
a.cpp:5:37: warning: implicit conversion changes signedness: 'size_t' (aka 'unsigned long long') to 'difference_type' (aka 'long long') [-Wsign-conversion]
    5 |     return std::count(str.begin() + start, str.begin() + end, c);
      |                                   ~ ^~~~~

在不更改 count_occurences

 签名的情况下修复这些警告的正确方法是什么?我当然可以在任何地方使用 static_cast
,但这更多的是消除警告而不是修复它。

(在实际代码中,

start

end
是字段,因此该函数只有2个参数。)

c++
1个回答
0
投票
您可以针对该功能单独关闭这些警告,但这不值得:

#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" size_t count_occurences(const std::string& str, char c, size_t start, size_t end) { return std::count(str.begin() + start, str.begin() + end, c); } #pragma clang diagnostic pop
请注意,GCC 会向您发出有关无法识别的编译指示的警告,因此您实际上需要的不仅仅是这个。

_Pragma

 可以帮助您最大限度地减少这种情况,但它仍然比仅使用 
size_t
 要复杂得多。

size_t count_occurences(const std::string& str, char c, size_t start, size_t end) { return std::count(str.begin() + static_cast<ptrdiff_t>(start), str.begin() + static_cast<ptrdiff_t>(end), c); }
这仍然是最自我记录的解决方案。
这可能不是一个令人满意的答案,但这是正确的方法。

根本问题是迭代器通常需要一个有符号整数,例如

ptrdiff_t

,而您正在使用无符号整数进行数学运算。
您的警告不是误报,并且 
static_cast
 将记录您意识到这些类型差异并有意进行转换。


注意:@TimRoberts 还指出你可以写 std::count(&str[start], &str[end], c);

。此解决方案仅适用于连续容器,但它比 
static_cast
 更紧凑。

© www.soinside.com 2019 - 2024. All rights reserved.