6

我需要将一个函数传递给操作员。任何具有正确 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 - 在前面的示例中可以简单地推断出返回类型。

EDIT2 很多人不明白需要什么,所以我改变了call功能以operator*使示例更真实。

4

3 回答 3

4

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

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

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

于 2012-07-28T02:26:46.437 回答
2

你应该能够做到这一点:

template<typename T,typename U>
U call (T x, U (*f)(T) ) {
      return (*f)(x);
};
于 2012-07-28T02:58:25.117 回答
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;
}
于 2012-07-28T05:53:39.720 回答