typedef'ing函数*签名*(不是指针),以便可以重用?

时间:2011-03-04 14:52:04

标签: c++ syntax function-pointers typedef

编辑:动机

假设我将Handler类定义为

class Handler {
public:
  class Message { /*...*/ };
  typedef int (*Callback)(Message *msg);
  void registerCallback(int msgclass, Callback f);
};

客户可以

int f1(Handler::Message *msg)
{ /* handle message */ }

int f2(Handler::Message *msg)
{ /* handle message */ }

int main(){
  Handler h;
  h.registerCallback(1, f1);
  h.registerCallback(2, f2);
  // ....
}

编译器确实会检查f1f2是否适合作为registerCallback的参数,但是,由客户端定义f1和{{1}正确的。由于我已经f2编辑typedef,我希望客户能够使用它。

结束编辑

我想做这样的事情:

Callback

然而,两者

typedef int arithmetic(int i, int j);

arithmetic sum
{
 return i+j;
}

arithmetic max
{
  return (i>j)? i:j;
}
// etc.

不编译,也是这个

arithmetic sum
arithmetic sum()

,它给出了

的编译错误
  

func.cpp:4:错误:'sum'声明为   函数返回函数

我想要这个的原因是我希望有一个arithmetic sum(int i, int j) 类,它为它接受的回调函数提供Handler包括参数列表。< / p>

5 个答案:

答案 0 :(得分:12)

我会给你一个经典的C答案,而不是诉诸于新奇的C ++ 0x玩具。让我们从定义函数原型开始:

typedef int TWO_ARG_FUNC(int x, int y);

接收函数指针时可以使用此原型,例如:

void blah(TWO_ARG_FUNC* funcPtr);

...或正向声明函数时:

TWO_ARG_FUNC max;

...但是你不能只通过编写原型来实现一个函数,例如:

TWO_ARG_FUNC max
{
   ... // bzzt, error!
}

然而,并非所有人都失去了。您可以通过首先向前声明它来强制执行该功能以保持原型:

TWO_ARG_FUNC max;

int max(int a, int b)
{
    ...
}

另一种选择是诉诸C宏:

#define DEFINE_TWO_ARG_FUNC(funcName) int funcName(int a, int b)

DEFINE_TWO_ARG_FUNC(max)
{
}

你甚至可以使用宏来声明一个函数原型,以防你以后想要声明一个指向这样一个函数的指针:

typedef DEFINE_TWO_ARG_FUNC(TWO_ARG_FUNC);

答案 1 :(得分:9)

首先,你没有输入一个签名。签名是标识单个功能的所有内容。它包含函数的名称空间/类等。

你输入的内容是函数的类型。就像你typedef int inttype类型定义int的类型一样,你输入定义函数的类型。

您可以使用typedef-name仅声明函数。

arithmetic max; // valid

但它不能用于定义函数。要定义函数,您需要按字面和手动提供参数列表。原因包括给出参数的名称(以及可能的其他更多技术原因.C ++ 0x引入arithmetic max {};将获得特定的初始化含义)。

答案 2 :(得分:3)

考虑一下你的帖子我会试一下你想要存档的内容。 您可以尝试使用boost或C ++ 0x lambda。我会继续提升。

typedef boost::function<int(int,int)> arithmetic;
arithmetic sum = (boost::lambda::_1 + boost::lambda::_2);
arithmetic max = boost::lambda::if_then_else_return(boost::lambda::_1 > boost::lambda::_2,
    boost::lambda::_1, boost::lambda::_2);

int j = sum(3,3); // j ist 6
int k = max(4,2); // k is 4

所以也许这就是你要存档的内容。

也可以使用完整的功能。 你走了。

int FullBodyFunction(int i, int j)
{
    return i+j;
}
arithmetic sum2 = boost::bind(&FullBodyFunction, _1, _2);

这与sum1相同。你可以自由使用整个boost绑定的东西。例如。绑定到对象的方法或任何你想要的东西。

答案 3 :(得分:2)

因为正如你所说,你可以使用C ++ 0x,你可以选择通过typedef'ing function来做类似的事情:

编辑,添加到包含回调typedef的处理程序类的概念中:

#include <functional>
#include <list>

int max(int a, int b)
{
    return (a>=b) ? a : b;
}

class Handler
{
    public:

        //typedef int (*Callback)(int, int);
        typedef std::function<int (int, int)> Callback;

        void add(Callback func) { functions_.push_back(func); }

    private:

        std::list<Callback> functions_;
};

int main(int argc, char* argv[])
{
    Handler handler;

    handler.add([](int a, int b) -> int { return (a>=b) ? a : b; });
    handler.add(max);

    return 0;
}

这不是您正在寻找的确切语法,但正如其他人所指出的那样,不能直接将typedef用于函数签名。

答案 4 :(得分:2)

我找不到您正在寻找的确切语法的解决方案,但这样的方法有效:

#include <cassert>

#define  arithmetic (int i, int j) -> int

#define declare(Func, Name) auto Name Func

#define as_

auto sum as_ arithmetic
{
  return i + j;
};

declare(arithmetic, max)
{
  return (i>j) ? i : j;
};

int main()
{
  assert(sum(2, 4) == 6);
  assert(max(2, 4) == 4);

  return 0;
}