如何将重载函数传递给运算符

How to pass overloaded function to an operator?

本文关键字:运算符 函数 重载      更新时间:2023-10-16

我需要将一个函数传递给一个运算符。任何具有正确arg类型的一元函数。返回类型可以是任何类型。因为这是库代码,所以我不能包装它,也不能将f强制转换为特定的重载(在operator*之外)。函数将operator*第一个参数作为自己的参数。下面的人工示例编译并返回正确的结果。但是它有一个硬编码的int返回类型——使这个例子可以编译。

#include <tuple>
#include <iostream>
using namespace std;
template<typename T>
int operator* (T x,  int& (*f)(T&) ) {
    return (*f)(x);
};
int main() {
    tuple<int,int>  tpl(42,43);
    cout << tpl * get<0>;
}

是否可以使operator*接受具有任意返回类型的f

更新-GCC错误代码:

#include <tuple>
template<typename T, typename U> 
U operator* (T x,  U& (*f)(T&) ) {  
    return (*f)(x);
}; 
int main() {
    std::tuple<int,int>  tpl(42,43);
    return   tpl * std::get<0,int,int>;
}  

使用gcc462和453正确编译和运行,但使用gcc471和480被拒绝。所以这可能是GCC回归错误。我已提交错误报告:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54111

编辑我已经将示例更改为使用元组作为arg——在前面的示例中,可以简单地推导出返回类型。

编辑2很多人无法理解需要什么,所以我将call函数更改为operator*,以使示例更加真实。

是的,如果这就是你的意思:

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

实际上有很多方法可以做到这一点。

作为您更新问题的答案:

正如@DavidRodríguez所讨论的,get<0>是不够的,语法正确的&get<0>也是不够的。您需要的是&get<0,int,int>。按照你的例子,它将是:

#include <tuple>
using namespace std;
template<typename T, typename U>
U call (T x, U (*f)(T&) ) {
      return (*f)(x);
};
int main() {
    tuple<int,int>  tpl(42,43);
    call(tpl, &get<0,int,int>);
    return 0;
}

std::get<>()的正常使用过程中,int,int部分是自动推导出来的。但在您的情况下,您需要提供它,因为没有参数。一种解决方法是自定义get模板函数:

#include <tuple>
using namespace std;
template <size_t I, typename T>
auto myGet(T& tpl) -> decltype(get<I>(tpl))
{
    return get<I>(tpl);
}
template<typename T, typename U>
U call (T x, U (*f)(T&) ) {
      return (*f)(x);
};

int main() {
    tuple<int,int>  tpl(42,43);
    auto get0 = &myGet<0, decltype(tpl)>;
    call(tpl, get0);
//  call(tpl, &myGet<0, decltype(tpl)>); // all in one line, do not work
    return 0;
}

您应该能够做到这一点:

template<typename T,typename U>
U call (T x, U (*f)(T) ) {
      return (*f)(x);
};