4
template <typename T>
void show(T&);       // #1
template <typename T>
void show(T const&); // #2

int main()
{
    int a = 0;
    show(a);        // #1 to be called
}

これらの部分的な順序付け規則について混乱しています。ここにいくつかの引用があります: [temp.deduct.partial]/5

部分的な順序付けが行われる前に、部分的な順序付けに使用される型に対して特定の変換が実行されます。

  • が参照型の場合Pは、参照される型にP置き換えられます。

  • が参照型の場合Aは、参照される型にA置き換えられます。

[臨時控除部分]/6

と の両方が参照型であった場合P(A上記の型に置き換えられる前)、2 つの型 (存在する場合) のどちらが他方よりも cv 修飾されているかを判断します。それ以外の場合、部分的な順序付けのために、型は同等に cv 修飾されていると見なされます。この判定結果を以下に使用する。

[臨時控除部分]/7

最上位の cv 修飾子をすべて削除します。

  • Pが cv 修飾された型である場合、 の cv 修飾Pされていないバージョンに置き換えられPます。

  • Aが cv 修飾された型である場合、 の cv 修飾Aされていないバージョンに置き換えられAます。

まず、 と の両方void show(T&)が左辺値void show(T const&)を渡すことで呼び出される可能性があるintため、半順序規則を使用して、どちらの関数がより一致するかを判断する必要があります。次に、上記の引用に従って、いくつかの変換を行います。ステップ1:

T&       => T          #3
T const& => T const    #4

ステップ2:

T       => T    #5
T const => T    #6

#5 => #6#6 => #5、演繹は両方向で成功します。次に、次のルールが機能します: [temp.deduct.partial]/9

特定の型について、演繹が両方向で成功し (つまり、上記の変換後に型が同一である)、両方が参照型PAあった場合 (上記の型に置き換えられる前):

  • 引数テンプレートの型が左辺値参照で、パラメーター テンプレートの型がそうでない場合、パラメーターの型は少なくとも引数の型と同じくらい特殊化されているとは見なされません。

  • それ以外の場合、引数テンプレートの型がパラメーター テンプレートの型よりも cv 修飾されている場合 (上記のように)、パラメーターの型は少なくとも引数の型と同じくらい特殊化されているとは見なされません。

その#4ため、より専門的#3です。指定された値に対してa#2関数を呼び出す必要がありますが、実際には#1関数が呼び出されます。なんで?私の理解に何か問題がありますか?

4

1 に答える 1