4 に答える
You got it the wrong way round. Default arguments don't participate in argument deduction:
Argument deduction happens first, as part of selecting the desired overload, and then the default arguments of that overload are filled in if necessary.
Kerrek SB が言ったことは正しいです。コンパイラには、(標準から許可されていることによって) T2 を推測するのに十分なものがありません。
この特定のケースでは、おそらくすべてに対して 1 つのテンプレート引数のみを使用することで修正できます。つまり、
template< class T > T inc( const T v, const T u = 1 ) { return v + u; }
デフォルトの引数は控除プロセスに参加しません(解決を過負荷にするためだけであり、ルールを覚えるのは非常に困難です-常に単純にしてください)。
必要なことを実現するために、追加のオーバーロードを提供できます。
template <class T1, class T2> T1 inc(T1 v, T2 u) { return v + u; }
template <class T> T inc(T v) { return v + T(1); }
C++ のテンプレート関数はコンパイル時に生成され、必要な場合にのみ生成されます。したがって、次のように生成された関数を取得できます。
inc( int, int );
T1 = int および T2 = int バージョンになります。すべてのテンプレート引数にパラメーターを渡すと、コンパイラーは暗黙的に型を判別できるため、次のようになります。
int a = 1;
int b = 2;
inc( a, b );
コンパイラは、T1 = int および T2 = int と推論できるため、コンパイル時に上記のような関数を生成できます。ただし、あなたがしていることを行う場合:
inc( 5 );
コンパイラは、T1 = int であると判断できますが、T2 が何かを判断することはできません。したがって、関数は生成されず、関数が存在しないというエラーが表示されます。これは、テンプレート パラメータを 1 つ使用すると修正できる場合があります。
template<class T> T inc(T v, T u = 1) { return v + u; }
または、オーバーロードを提供する場合:
template<class T> T inc(T v) { return v + 1; }
3 番目の方法もあります。
inc<int, int>( 5 );
しかし、これはあなたが望むものではないと思います...