4

次のデモコードがあります。

template <int i, typename T, typename U>
T func(const U &t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>(1);
}

これは私の実際のコードの煮詰めたバージョンなので、役に立たないように見えますが、問題を示すには十分なはずです:

In function ‘int main()’:                                                  
11:23: error: call of overloaded ‘func(int)’ is ambiguous
11:23: note: candidates are:
2:3: note: T func(const U&) [with int i = 1, T = int, U = int]
5:3: note: T func(const T&) [with int i = 1, T = int]

したがって、自動型推論 (テンプレート パラメーター U の場合) が、テンプレート関数の正しいバージョン (パラメーターが 2 つしかないバージョン) を選択するという私の興味を妨げることは明らかです。

少し異なることを行う基本的なテンプレートと特殊なテンプレートを両方のバージョンに用意する必要があります。

質問は次のとおりです。この時点で型を自動的に推論しないようにコンパイラに指示する可能性はありますか (たとえば、パラメータが 2 つしかないテンプレートを使用するなど)。

4

2 に答える 2

4

型推論を無効にすることはできませんが、SFINAE を使用してオーバーロードの 1 つを禁止できます。

template <int N, typename T, typename U>
typename std::enable_if< !std::is_same<T,U>::value, T >::type
func( const U & t ) {
   return i*t;
}

Uこれは基本的に、推論された型がtype である場合に置換が失敗するテンプレート化された関数を作成します。そのT時点で、SFINAE は潜在的な候補のセットからテンプレートを削除し、他のテンプレートが選択されます。

C++11 対応のコンパイラがない場合、enable_ifis_sameテンプレートは簡単に記述できます。Google で検索するか、コメントをドロップするだけです。

于 2012-03-30T15:07:19.120 に答える
1

イニシャライザリストを渡すと、推論を効果的に無効にできます(ただし、この場合はint同じ効果を持つパラメータのリスト初期化が発生します)。

template <int i, typename T, typename U>
T func(const U &t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>({1});
}

しかし、あなたの場合、func<N>(...)電話すると2番目のものを呼び出したいようで、電話func<N, T>(...)すると常に2番目のものも呼び出しfunc<N, T, U>(...)たいようで、最初のものだけを呼び出したいので、いつでも無効にすることができますパラメータUを非推定コンテキストにすることによる推定

template <int i, typename T, typename U>
T func(typename std::common_type<const U &t>::type t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>({1});
}
于 2012-03-31T19:02:02.363 に答える