webdevqa.jp.net

C ++関数タイプ

関数タイプの理解に問題があります(たとえば、std::functionSignatureテンプレートパラメータとして表示されます):

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"

私はここで言語のどの辺境をたどったのですか?この奇妙な型はどのように呼び出され、テンプレートパラメータの外で何を使用できますか?

19
marton78

これは規格の関連する段落です。それはほとんどそれ自体のために語っています。

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
21
aschepler

あなたの場合、_std_fun_1_と_std_fun_2_は、同じ型シグネチャを持つ同じオブジェクトです。これらはどちらもstd::function<int(int)>であり、どちらもint(int)型の関数ポインタまたは呼び出し可能オブジェクトを保持できます。

pfint(int)へのポインターです。つまり、_std::function_と同じ基本的な目的を果たしますが、そのクラスの機構や呼び出し可能なオブジェクトのインスタンスのサポートはありません。

同様に、_std_fun_3_と_std_fun_4_は、同じ型シグネチャを持つ同一のオブジェクトであり、どちらも関数ポインタまたはint(int) const型の呼び出し可能オブジェクトを保持できます。

同様に、pfcint(int) const型の関数ポインターであり、その型の関数へのポインターを保持できますが、呼び出し可能なオブジェクトのインスタンスは保持できません。

ただし、ffc関数宣言です

この線:

_Signature fc;
_

次と同等です:

_int fc(int) const;
_

これは、タイプint(int) constfcという名前の関数の宣言です。

ここで奇妙なことは何もありません。慣れていない視点から、おそらくすでに理解している構文に遭遇しただけです。

2
greyfade