16

次のコードを検討してください。

#include <iostream>

template<typename T>
void inc1(T&& x)
{
    T y = x;
    ++y;
}

template<typename T>
void inc2(T& x)
{
    T y = x;
    ++y;
}

int main()
{
    int a = 10;
    inc1(a); // a is now 11

    int b = 10;
    inc2(b); // b remains 10
}

置換後、

void inc1(int& x)
{
    int& y = x; // reference to x
    ++y; // increments x
}

void inc2(int& x)
{
    int y = x; // copy of x
    ++y; // increments the copie
}

ではinc1、との両方が参照ですが、両方が右辺値ではないため、xは型です。int&int&T&&

同様に、 ininc2xtypeです。これも、とのint&両方が参照ですが、両方が右辺値であるわけではないためです。int&T&

私の質問は次のyとおりです。なぜ inは typeinc1であるのに対し、 inはtype なのですか?yint&inc2yint

これは、gcc 4.8.1 と Microsoft v110 および v120_ctp の両方で観察されました。

4

2 に答える 2

7

S14.8.2.1 [temp.deduct.call] 言います:

テンプレート引数の推定は、以下で説明するように、各関数テンプレート パラメーターの型 (P と呼びます) を呼び出しの対応する引数の型 (A と呼びます) と比較することによって行われます。

そのため、 type の A を指定して P を計算しようとしていますint

S14.8.2.3 続き:

P が cv 修飾された型の場合、P の型の最上位の cv 修飾子は型推定では無視されます。P が参照型の場合、P によって参照される型が型推定に使用されます。P が cv 非修飾テンプレート パラメーターへの右辺値参照であり、引数が左辺値である場合、型推定のために A の代わりに型「A への左辺値参照」が使用されます。[ 例:

template <class T> int f(T&&);         // <--- YOUR TEMPLATE IS LIKE THIS
template <class T> int g(const T&&);
int i;
int n1 = f(i); // calls f<int&>(int&)  // <--- YOUR CALL IS LIKE THIS
int n2 = f(0); // calls f<int>(int&&)
int n3 = g(i); // error: would call g<int>(const int&&), which
               // would bind an rvalue reference to an lvalue

—終わりの例]

あなたの呼び出しはf(i)例のようです-これはフォームの関数をインスタンス化しますf<int&>(int&)...つまりTis です。これがへの参照を作成するint&理由です。T y = xx

Scott Meyers のページ ( http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers ) も参照してください。

于 2013-06-04T06:55:19.377 に答える