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

时间:2012-07-28 02:24:27

标签: c++ templates c++11 operator-overloading function-pointers

我需要将一个函数传递给一个操作符。任何具有正确arg类型的一元函数。返回类型可以是任何东西。因为这是库代码,所以我无法将其包装或将f转换为特定的重载(operator*之外)。函数将operator* 1st arg作为自己的参数。下面的人工示例编译并返回正确的结果。但它已经硬编码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的例子 - 在前面的例子中可以简单地推断出返回类型。

EDIT2 许多人无法理解需要什么,因此我将call函数更改为operator*以使示例更加真实。

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:2)

你应该可以这样做:

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

答案 2 :(得分:2)

作为对最新问题的回答:

正如@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;
}