函子上显式转换函数的基本原理
Rationale for explicit conversion function on functor
当我短暂休息时,我的工作场所转而使用静态代码分析器。
他们 运行 我正在处理的项目,分析器标记的一个特定问题是这样的(简化示例):
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) 代码付出的代价。
side note: TIL that explicit
applies not only to ctors
编辑
似乎有些人无法阅读我提供的示例代码(漂亮的教科书内容)并且仍然建议其他 algorithms/idioms,完全没有看到实际问题是关于函子的转换运算符,其唯一目的是计算和 return 算法的结果。
如果问题是关于如何改进加法算法,那么标题就会这么说。
所以我决定在这次编辑中隐藏所有实施细节,让这些人更轻松。
抱歉,下面的一些评论现在不再有任何意义,但记录卡住了,所以我不得不稍微移动一下指针以推动事情向前发展(希望如此)。
我会完全取消任何转换运算符。有什么问题:
int result = std::for_each(...).get();
其中 get()
与您当前的 operator int
相同。
你知道 for_each 的结果不是整数,它是你的函数对象。为什么,为什么要避免从函数到值的显式转换?无论如何,这是一个值得怀疑的想法。当然,您仍然可以这样做,但是您想要干净无警告的代码,对吧?好吧,在我的书中,干净、无警告的代码不应将函数自动转换为整数。我同意 static_cast
几乎同样丑陋,这就是为什么我建议命名函数
当我短暂休息时,我的工作场所转而使用静态代码分析器。 他们 运行 我正在处理的项目,分析器标记的一个特定问题是这样的(简化示例):
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) 代码付出的代价。
side note: TIL that
explicit
applies not only to ctors
编辑
似乎有些人无法阅读我提供的示例代码(漂亮的教科书内容)并且仍然建议其他 algorithms/idioms,完全没有看到实际问题是关于函子的转换运算符,其唯一目的是计算和 return 算法的结果。
如果问题是关于如何改进加法算法,那么标题就会这么说。
所以我决定在这次编辑中隐藏所有实施细节,让这些人更轻松。
抱歉,下面的一些评论现在不再有任何意义,但记录卡住了,所以我不得不稍微移动一下指针以推动事情向前发展(希望如此)。
我会完全取消任何转换运算符。有什么问题:
int result = std::for_each(...).get();
其中 get()
与您当前的 operator int
相同。
你知道 for_each 的结果不是整数,它是你的函数对象。为什么,为什么要避免从函数到值的显式转换?无论如何,这是一个值得怀疑的想法。当然,您仍然可以这样做,但是您想要干净无警告的代码,对吧?好吧,在我的书中,干净、无警告的代码不应将函数自动转换为整数。我同意 static_cast
几乎同样丑陋,这就是为什么我建议命名函数