当我短暂休息时,我的工作场所改用静态代码分析器。 他们在我正在处理的项目上运行了它,分析器标记的一个特定问题如下所示(简化示例):
struct calcSomething
{
int result;
calcSomething() : result(0) {}
void operator()(const int v) { /*does something*/ }
operator int() const { return result; }
};
void foo()
{
std::vector<int> myvector(10);
// exercise for reader: stick some values in `myvector`
int result = std::for_each(myvector.begin(), myvector.end(), calcSomething());
}
分析器标记以下问题:
warning: CodeChecker: 'operator int' must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
operator int() const { return result; }
对函子的建议修复如下:
struct calcSomething
{
...
explicit operator int() const { return result; }
};
但是,如果我按照建议修复函子,静态分析器会快速标记以下问题:
warning: CodeChecker: no viable conversion from '(anonymous namespace)::calcSomething' to 'int' [clang-diagnostic-error]
我现在需要添加显式转换:
void foo()
{
...
int total = static_cast<int>(std::for_each(myvector.begin(), myvector.end(), calcSomething()));
}
上面的例子只是对实际问题的简化,否则只会添加填充物而不是任何实质内容。
我见过很多函子的例子,就像我在教科书和编程参考网页中描述的那样。 我从来没有认为这些不安全。我从未见过有人将这些标记为不安全。
那么代码分析器有道理吗? 或者让我的函子的转换运算符显式化并因此让我添加静态转换是否有点过分热心?
纯粹从美学角度来看,我觉得一个简单的问题加上优雅的解决方案现在会产生很多丑陋的语法填充。 但这也许就是我们编写安全(r)代码所付出的代价。
旁注:直到
不仅适用于演员explicit
编辑
似乎有些人无法阅读我提供的示例代码(漂亮的教科书内容)之外的内容,并且仍然建议其他算法/习惯用法,完全看不到实际问题是关于函子上的转换运算符,其唯一目的是计算和返回算法的结果。
如果问题是关于如何改进加法算法,那么标题就会这么说。
因此,我决定在此编辑中隐藏任何实现细节,以使这些人更容易。
抱歉,下面的一些评论现在不再有任何意义,但记录被卡住了,所以我不得不稍微移动一下,以便推动事情向前发展(希望如此)。
我会完全取消任何转换运算符。有什么问题:
int result = std::for_each(...).get();
其中
get()
与您当前的 operator int
相同。
你知道 for_each 的结果不是整数,它是你的函数对象。为什么,为什么要避免显式地从函数到值的转换?无论如何,这是一个值得怀疑的想法。当然,您仍然可以这样做,但您想要干净、无警告的代码,对吧?好吧,在我的书中,干净、无警告的代码不应该自动将函数转换为整数。我同意
static_cast
几乎同样丑陋,这就是为什么我建议使用命名函数