如何避免在获取标准库函数地址时出现非标准行为

huangapple go评论84阅读模式
英文:

How to avoid non-standard behavior in taking the address of a standard library function

问题

阅读有关指定可寻址函数的内容后,我意识到获取标准库函数的地址是未定义行为。

现在,我不知道如何重写我的代码,以始终获取标准函数的地址。

  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. bool divisible_3(double n){
  5. return int(n)%3==0;
  6. }
  7. void applyFunction(std::vector<double>& vector, bool(* filterf)(double), double(*calc)(double)){
  8. for(int index=0;index<int(vector.size());index++){
  9. if(filterf(vector[index])){
  10. vector[index]=calc(vector[index]);
  11. }
  12. }
  13. }
  14. int main(){
  15. std::vector<double> vect = {1, 2, 3, 5, 9, 16, 21, 24};
  16. applyFunction(vect,divisible_3,std::sqrt);
  17. for(auto&& i: vect){
  18. std::cout << i << std::endl;
  19. }
  20. }
英文:

Reading about Designated addressable functions, I realized that taking the address of a standard library function is undefined behavior.

Now, I do not know how to rewrite my code that always take the address of standard functions.

  1. #include &lt;iostream&gt;
  2. #include&lt;vector&gt;
  3. #include&lt;cmath&gt;
  4. bool divisible_3(double n){
  5. return int(n)%3==0;
  6. }
  7. void applyFunction(std::vector&lt;double&gt;&amp; vector, bool(* filterf)(double), double(*calc)(double)){
  8. for(int index=0;index&lt;int(vector.size());index++){
  9. if(filterf(vector[index])){
  10. vector[index]=calc(vector[index]);
  11. }
  12. }
  13. }
  14. int main(){
  15. std::vector&lt;double&gt; vect = {1, 2, 3, 5, 9, 16, 21, 24};
  16. applyFunction(vect,divisible_3,std::sqrt);
  17. for(auto&amp;&amp; i: vect){
  18. std::cout &lt;&lt; i &lt;&lt; std::endl;
  19. }
  20. }

答案1

得分: 5

以下是翻译好的部分:

有几种选择。第一种最明显:编写自己的代理函数。 std::sqrt 可能是一个不可寻址的函数,但你知道什么是可寻址的吗?

  1. double totally_not_std_sqrt(double input) {
  2. return std::sqrt(input);
  3. }

这个函数是完全可寻址的,因此它可以作为参数传递到完全标准的C++中。

另一种更紧凑的选择是使用 lambda 表达式。

  1. applyFunction(vect, divisible_3, [](double x) { return std::sqrt(x); });

现在你可能会想:“lambda 可以转换为 std::function,但我需要一个函数指针”。这是正确的。但是,不捕获的 lambda 可以转换为函数指针,因此即使你的函数接受函数指针,它仍然可以接受不捕获的 lambda 表达式。(不过,除非你打算与C接口交互,否则你可能考虑让你的函数接受 std::function,但这是另一个问题)

英文:

There are a few choices. The first is the most obvious: write your own delegator function. std::sqrt might be a non-addressable function, but you know what is addressable?

  1. double totally_not_std_sqrt(double input) {
  2. return std::sqrt(input);
  3. }

This function is entirely addressable, so it can be passed in as an argument in completely standard C++.

The other, more compact option is to use a lambda.

  1. applyFunction(vect, divisible_3, [](double x) { return std::sqrt(x); });

Now you might be thinking "lambdas are convertible to std::function, but I take a function pointer". That's true. But lambdas that don't capture are convertible to function pointers, so even though your function takes a function pointer, it can still take non-capturing lambdas. (You might consider having your function take std::function though, unless you're planning on interfacing with C, but that's another issue)

huangapple
  • 本文由 发表于 2023年4月20日 10:42:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76060137.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定