6

以下のコードはコンパイル (gcc 4.7.2 または icc 13) し、「1 2」出力を生成します。これは、const修飾子が削除されたことを意味します。つまり、f<int&>パラメーター type がありますint&

なぜそれが起こるのですか?私が理解しているように、§14.3.1.4 によると:

template-parameter のテンプレート引数がT型「cv1 への参照」を指定する場合、型「cv2 Sへの参照」を作成しようとすると、型「cv12 Tへの参照」が作成されます S。ここで、cv12は cv 修飾子 cv1 の和集合ですおよびcv2。冗長な cv 修飾子は無視されます。

const落としてはいけません。コードは次のとおりです。

#include <iostream>
using namespace std;

template <typename T>
void f(const T& t)
{
    t++;
}

int main()
{
    int a = 1;

    cout << a;
    f<int&>(a);
    cout << ' ' << a << endl;

    return 0;
}
4

2 に答える 2

5

フラグが指定されている場合、GCC 4.7.2 はこれをコンパイルしませ-std=c++98。実際、C++98 (および C++03) では、参照への参照は折りたたまれません。

f<int&>whereをインスタンス化しようとするとT = int&、次の関数シグネチャが生成されます (ここでは、引数の型Tconst指定子の位置を意図的に入れ替えてconst T&T const&ます。

void f(int& const& t) // ERROR: reference to reference is illegal

上記は C++98 でも C++03 でも正しくありません。一貫して、これは GCC 4.7.2 から得られるエラーです。

Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:15:14: error: no matching function for call to 'f(int&)'
source.cpp:15:14: note: candidate is:
source.cpp:5:6: note: template<class T> void f(const T&)
source.cpp:5:6: note:   template argument deduction/substitution failed:
source.cpp: In substitution of 'template<class T> void f(const T&) [with T = int&]':
source.cpp:15:14:   required from here
source.cpp:5:6: error: forming reference to reference type 'int&'

それにもかかわらず、フラグを使用すると-std=c++11、コンパイラはテンプレートをインスタンス化するときに参照の折りたたみを実行します。左辺値参照への左辺値参照は左辺値参照になります。

void f(int& const& t) == void f(int& t)

ここでconst修飾子は削除されます。これは、参照先のオブジェクトではなく参照に適用されるためです。参照は再割り当てできないためconst、本質的に存在します。そのため、constは不要であると見なされ、削除されます。説明については、 SO に関するこの Q&A を参照してください。

これにより、単純な左辺値参照に解決される左辺値参照への左辺値参照が生成されます。したがって、右側の署名がインスタンス化されます。

上記は、呼び出しを解決する実行可能な候補であるf<int&>(a)ため、エラーなしでコンパイルされます。

于 2013-02-07T21:56:20.490 に答える
5

問題の引用が始まったと思われる1770年は次のとおりです。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html

14.3.1 - テンプレート型引数

-4- テンプレートパラメータ T のテンプレート引数が型「cv1 S への左辺値参照」を指定する場合、「cv2 T への (左辺値または右辺値) 参照」型を作成しようとすると、「左辺値参照」型が作成されます。ここで、cv12 は cv 修飾子 cv1 と cv2 の和集合です。テンプレート引数が「cv1 S への右辺値参照」型を指定する場合、「cv2 T への左辺値参照」型を作成しようとすると、「cv12 S への左辺値参照」型が作成されます。テンプレート引数が「cv1 S への右辺値参照」型を指定する場合、「cv2 T への右辺値参照」型を作成しようとすると、「cv12 S への右辺値参照」型が作成されます。冗長な cv 修飾子は無視されます。

2118 の引用を取り消したものを次に示します。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html

14.3.1 - テンプレート型引数

-4- テンプレート パラメータ T のテンプレート引数が、型 A への参照である型「cv1 S への参照」を指定する場合、型「cv2 T への参照」「cv への左辺値参照」を作成しようとします。T" は、型"cv12 S への参照" を作成します。ここで、cv12 は、cv 修飾子 cv1 と cv2 の和集合です。冗長な cv 修飾子は「A への左辺値参照」は無視されますが、「cv T への右辺値参照」型を作成しようとすると、型 T が作成されます。

あなたが引用しているのは時代遅れの言葉遣いのようです。

于 2013-02-07T21:59:05.533 に答える