gpt4 book ai didi

c++ - 将 C++ 重载函数指针提升到函数对象

转载 作者:太空狗 更新时间:2023-10-29 20:06:03 27 4
gpt4 key购买 nike

接受函数对象参数的 C++11 模板函数,例如:

template <typename F, typename T>
auto foo(F f, T x) -> decltype(f(x)) {
return f(x);
}

可以采用如下函数:

int succ(int i) { return i+1; }

并申请foosucc并获得结果 10:

foo(succ,9);

重载函数不起作用,sin ,例如,失败:

foo(std::sin,0.5);

在 GCC (4.7) 中“无法推断模板参数 F”。

(顺便说一句,提供 sin<double> 仅与复杂类型有关。)是的,我可以直接构造它:

template <typename T>
struct Sin {
T operator()(T x) { return std::sin(x); }
};

有一点:

foo(Sin<double>(),0.5);

我的问题是,是否有替代方案可以避免需要这样一个新定义;只能在 foo 的调用站点使用?

最佳答案

对于函数指针,您可以简单地让用户键入签名:

template<class F, class T>
void foo(F f, T x){
f(x);
}

void bar(int){}
void bar(double){}

int main(){
foo<void(int)>(bar, 5);
}

Live example on Ideone .

foo将是 void foo(void f(int), int x)替换后,与 foo(void (*f)(int), int x) 相同.这提供了一个所谓的“调用上下文”,允许编译器选择正确的重载。显然,这只有在第一个模板参数是函数时才有效。要解决此限制并使其看起来更好(恕我直言,至少),您可以提供一个简单的辅助函数:

template<class F>
auto get_overload(F f) -> decltype(f) { return f; }

实际上,您只能重载参数类型,但是您不能排除让用户键入返回类型的需要,因为这会再次禁用调用上下文,因为需要推导类型。

因为您很可能(或肯定)只想将它用于函数指针,您可以将其更改为:

template<class F>
F* get_overload(F* f){ return f; }

还是完全一样。第一个版本不能只有 F 的唯一原因因为返回类型是 Fvoid(int)如果你用 get_overload<void(int)>(bar) 调用它,并且标准不允许您返回函数(是的,这是一种函数类型)。函数指针转换的函数 ( void(int) -> void(*)(int) ) 部分只发生在参数上。


由于@VJovic 出于某种原因删除了他的回答,我将在以下位置对其进行编辑:

您实际上可以使用简单的 lambda 代替 get_overload功能。它将在字符方面大致相同长度,并且更加方便和清晰。它还会更高效,因为不涉及(函数)指针,并且编译器完全能够内联调用。

foo([](int i){ return bar(i); }, 5);

关于c++ - 将 C++ 重载函数指针提升到函数对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9832418/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com