英文:
How to avoid non-standard behavior in taking the address of a standard library function
问题
阅读有关指定可寻址函数的内容后,我意识到获取标准库函数的地址是未定义行为。
现在,我不知道如何重写我的代码,以始终获取标准函数的地址。
#include <iostream>
#include <vector>
#include <cmath>
bool divisible_3(double n){
return int(n)%3==0;
}
void applyFunction(std::vector<double>& vector, bool(* filterf)(double), double(*calc)(double)){
for(int index=0;index<int(vector.size());index++){
if(filterf(vector[index])){
vector[index]=calc(vector[index]);
}
}
}
int main(){
std::vector<double> vect = {1, 2, 3, 5, 9, 16, 21, 24};
applyFunction(vect,divisible_3,std::sqrt);
for(auto&& i: vect){
std::cout << i << std::endl;
}
}
英文:
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.
#include <iostream>
#include<vector>
#include<cmath>
bool divisible_3(double n){
return int(n)%3==0;
}
void applyFunction(std::vector<double>& vector, bool(* filterf)(double), double(*calc)(double)){
for(int index=0;index<int(vector.size());index++){
if(filterf(vector[index])){
vector[index]=calc(vector[index]);
}
}
}
int main(){
std::vector<double> vect = {1, 2, 3, 5, 9, 16, 21, 24};
applyFunction(vect,divisible_3,std::sqrt);
for(auto&& i: vect){
std::cout << i << std::endl;
}
}
答案1
得分: 5
以下是翻译好的部分:
有几种选择。第一种最明显:编写自己的代理函数。 std::sqrt
可能是一个不可寻址的函数,但你知道什么是可寻址的吗?
double totally_not_std_sqrt(double input) {
return std::sqrt(input);
}
这个函数是完全可寻址的,因此它可以作为参数传递到完全标准的C++中。
另一种更紧凑的选择是使用 lambda 表达式。
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?
double totally_not_std_sqrt(double input) {
return std::sqrt(input);
}
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.
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论