28

我在理解函数类型时遇到问题(例如,它们显示为Signaturea 的模板参数std::function):

typedef int Signature(int); // the signature in question

typedef std::function<int(int)>  std_fun_1;
typedef std::function<Signature> std_fun_2;

static_assert(std::is_same<std_fun_1, std_fun_2>::value,
              "They are the same, cool.");

int square(int x) { return x*x; }

Signature* pf = square;   // pf is a function pointer, easy
Signature f;              // but what the hell is this?
f(42);                    // this compiles but doesn't link

变量f不能赋值,但可以调用。诡异的。那有什么用呢?

现在,如果我对 typedef 进行 const 限定,我仍然可以使用它来构建更多类型,但显然没有别的:

typedef int ConstSig(int) const;

typedef std::function<int(int) const>  std_fun_3;
typedef std::function<ConstSig>        std_fun_4;

static_assert(std::is_same<std_fun_3, std_fun_4>::value,
              "Also the same, ok.");

ConstSig* pfc = square; // "Pointer to function type cannot have const qualifier"
ConstSig fc;            // "Non-member function cannot have const qualifier"

我在这里遇到了语言的哪个偏远角落?这种奇怪的类型是如何调用的,我可以在模板参数之外使用它做什么?

4

2 回答 2

28

这是标准中的相关段落。它几乎不言自明。

8.3.5/10

函数类型的 typedef 可用于声明函数,但不得用于定义函数 (8.4)。

例子:

typedef void F();
F  fv;         // OK: equivalent to void fv();
F  fv { }      // ill-formed
void fv() { }  // OK: definition of fv

声明符包含cv-qualifier-seq的函数类型的 typedef只能用于声明非静态成员函数的函数类型,声明指向成员的指针所指的函数类型,或声明顶部另一个函数 typedef 声明的级别函数类型。

例子:

typedef int FIC(int) const;
FIC f;               // ill-formed: does not declare a member function
struct S {
  FIC f;             // OK
};
FIC S::*pm = &S::f;  // OK
于 2013-07-03T11:18:47.087 回答
3

在您的情况下,std_fun_1std_fun_2是具有相同类型签名的相同对象。它们都是std::function<int(int)>,并且都可以保存函数指针或类型的可调用对象int(int)

pf是指向 的指针int(int)。也就是说,它与 具有相同的基本目的std::function,但没有该类的机制或支持可调用对象的实例。

同样,std_fun_3std_fun_4是具有相同类型签名的相同对象,并且都可以保存函数指针或类型的可调用对象int(int) const

同样,pfc是一个类型的函数指针int(int) const,并且可以保存指向该类型函数的指针,但不能保存可调用对象的实例。

但是fandfc函数声明。

该行:

Signature fc;

等同于:

int fc(int) const;

这是一个名为fctype的函数的声明int(int) const

这里没有什么奇怪的。从您不习惯的角度来看,您只是碰巧遇到了您可能已经理解的语法。

于 2013-07-03T11:16:54.007 回答