C++ 用語のランダムなシーケンスで構成された別の質問タイトルです!
通常は、 を実装して Callable クラスを作成しますoperator()
。ただし、関数ポインターまたは参照型へのユーザー定義の変換を実装することで、これを行うこともできます。完全な転送を使用する代わりに、変換関数は、元の引数リストで呼び出される関数へのポインターを返すことができます。
struct call_printf {
typedef int printf_t( char const *, ... );
operator printf_t & () { return std::printf; }
};
私の知る限り、typedef
上記は構文上の必要性です。変換関数の名前はtype-specifier-seqから形成され、 のような構成は許可されませんint (*)()
。それにはabstract-declaratorが必要です。おそらくその理由は、そのような型名が複雑になり、オブジェクト名として使用される複雑な構造が解析しにくいためです。
変換関数もテンプレート化できますが、明示的に指定する場所がないため、テンプレート引数を推定する必要があります。(それは暗黙の変換のポイント全体を無効にします。)
質問 #1: C++03 では、関数変換演算子のテンプレートを指定する方法がありませんでしたか? テンプレート引数を解決する (つまり、推測されたコンテキストで名前を付ける) 方法が、受け入れ可能な関数ポインター型でないように見えます。
これは、C++11、§13.3.1.1.2/2 [over.call.object] からの同等の参照です。C++03 と実質的に同じです。
さらに、次の形式の T で宣言された非明示的な変換関数ごとに、
operator conversion-type-id () cv-qualifier attribute-specifier-seqopt;
ここで、cv-qualifierは cv と同じ cv-qualification、または cv より大きい cv-qualification であり、conversion -type-idは「R を返す (P1,...,Pn) の関数へのポインター」型を示します。または型「R を返す (P1,...,Pn) の関数へのポインタへの参照」、または型「R を返す (P1,...,Pn) の関数への参照」、一意の名前 call-function とフォームを持つ
R call-function ( conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); }
も候補関数と見なされます。同様に、代理呼び出し関数は、T の基本クラスで宣言された各非明示的な変換関数の候補関数のセットに追加されますが、その関数が別の介在する宣言によって T 内に隠されていなければなりません。
質問 #2: C++11 では、デフォルトのテンプレート引数を使用してそのような変換を指定できますか? これは SFINAE に役立ちます。上記の例との唯一の違いは、conversion-type-idがインスタンス化後の関数参照のみを表すことです。これは、依存型であるためです (不変性にもかかわらず)。これにより GCC がトリップし、メンバー テンプレートがスキップされます。
enum { call_alternate = true; }
struct call_switch {
template< bool en = call_alternate >
operator typename std::enable_if< en, decltype( fn_1 ) & >::type ()
{ return fn_1; }
template< bool en = ! call_alternate >
operator typename std::enable_if< en, decltype( fn_2 ) & >::type ()
{ return fn_2; }
};
エイリアス テンプレートもあります。競合の宣言がある §14.5.7/2 の例を考えると、エイリアス置換はインスタンス化の前に発生するようですprocess
。GCC 4.7 では、このコードは少なくとも宣言をインスタンス化しますが、奇妙な「候補は 2 つの引数を期待し、2 つが提供されます」というエラーを生成します。
template< typename t >
using fn_t = void (&)( t );
struct talk {
template< typename t >
operator fn_t< t >() { return fn; }
};
int main() {
talk()( 3 );
}