12

関数をオーバーロードしてから、オーバーロードの1つと完全に一致する引数を使用して関数を呼び出す場合

int f(int){return 3;}
int f(bool){return 4;}
...        //inside main()
f(1);      //Calls f(int)

コンパイラーは、暗黙の変換を試みる前に、この(完全な)一致を選択するだけです。しかし、私は関数temp→ateをオーバーロードしようとしています。

template <bool veracity>
int f(){return 1;}

template <int amount>
int f(){return 2;}

...        //inside main()
f<1>();

しかし、コンパイラーは、オーバーロードされたf()へのあいまいな呼び出しについて不平を言い続け、それがまたはのいずれかである可能性があると述べていf<true>()ますf<1>()コンパイラは、 1trueに変換しようとするのではなく、完全に一致するものを選択するべきではありませんか?

テンプレート引数の暗黙的な変換は、実際には関数の引数の暗黙的な変換よりも制限的であるという印象を受けました。この問題を回避する方法はありますか?

4

2 に答える 2

8

提供する引数は型ではなく値であるため、ルールは少し異なります。型以外の引数にルールを適用する必要があります。非型引数の場合、暗黙的な変換が許可されます。§14.3.2/5:

以下の変換は、非型テンプレート引数として使用される各式で実行されます。非型のtemplate-argumentを対応するtemplate-parameterの型に変換できない場合、プログラムの形式は正しくありません。

—整数型または列挙型の非型テンプレートパラメータの場合、変換された定数式(5.19)で許可されている変換が適用されます。

C ++ 03では、表現はわずかに異なりますが、効果は本質的に同じです(§14.3.2/ 5も):

—整数型または列挙型の非型テンプレートパラメータの場合、整数拡張(4.5)および積分変換(4.7)が適用されます。

いずれにせよ、1はでありint、暗黙的にに変換可能であるためbool、呼び出しはあいまいです。

于 2012-04-05T15:44:32.743 に答える
5

これはコンパイラのバグではなく、言語機能(この回答を参照)であるため、回避策を見つける必要があります。

関数の名前を変更する必要があるか、次のハックを使用できます。

template <typename T> struct F;

template<> struct F<bool> {
  template <bool veracity>
  static int f(){return 1;}
};

template<> struct F<int> {
  template <int amount>
  static int f(){return 2;}
};

template <typename T, T value>
int f() { return F<T>::template f<value>(); }

// inside main():
std::cout << f<int,  2>() << '\n'; // prints 2
std::cout << f<bool, 2>() << '\n'; // prints 1
于 2012-04-05T15:52:21.283 に答える