Soru C ++ şablon işlevinin davranışı


Diyelim ki bu fonksiyona sahibim:

bool f(int&& one, int&& two) { }

Bu kodla aramayı denerseniz:

int x = 4;
f(x, 5);

Derleyici, x değerini lvalue referansından doğru referansa dönüştüremediğinden şikayet eder.

Şimdi f'yi bir şablon işlevine dönüştürürsem:

template <class T, class U>
bool f(T&& one, U&& two) { }

o zaman bir lvalue referansı ile arayabilirim:

int x = 5;
f(x, 5);

Neden böyle? Derleyici neden bu durumda şikayet etmiyor?


18
2017-10-03 07:24


Menşei




Cevaplar:


Bir şablon argüman kesintisi olduğundan, referans çökmesi olur. Scott Meyers'ın dediği şey bu. evrensel referanslar. U&& aslında olacak int &. Güzel bir şey var makale ve video nasıl çalıştığı ve nasıl kullanılabileceği hakkında.


8
2017-10-03 07:31





§ 8.3.3 / 6'ya göre. Referans çöken kuralıdır.

template <class T> void func(T&&)  // Accepts rvalue or lvalue
void func(T&&)                     // Accepts rvalue only
void func(T&)                      // Accepts lvalue only

Standart taslaktan örnek değer:

int i;
typedef int& LRI;
typedef int&& RRI;

LRI& r1 = i;           // r1 has the type int&
const LRI& r2 = i;     // r2 has the type int&
const LRI&& r3 = i;    // r3 has the type int&

RRI& r4 = i;           // r4 has the type int&
RRI&& r5 = 5;          // r5 has the type int&&

decltype(r2)& r6 = i;  // r6 has the type int&
decltype(r2)&& r7 = i; // r7 has the type int&

10
2017-10-03 07:28



Bu bir çeşit karşı sezgisel ... - Violet Giraffe
@VioletGiraffe C ++ 'nın dünyasına hoş geldiniz - jk.
@jk .: Ve ben bu dünyanın çoğunu anladığımı düşünüyordum! - Violet Giraffe
Sadece referans çöküşü değil, aynı zamanda indirgeme özelliklerinde bir tuhaflık da vardır, bkz. [Temp.deduct.call] / 3. (Ayrıca, 8.3.3 / 6 değil, 8.3.3 / 6'ya atıf yaptığınızı düşünüyorum) - dyp


Bu, c ++ 11'de eklenen referans daraltma kuralları nedeniyle olur

A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&

Şablonlarda bu kurallar uygulanır, ancak normal bir işlevde değil, normal olarak işlevde çöken bir referans yoktur. Varlığında referans çöküşünün meydana geleceği bazı özel durumlar vardır. auto, decltype ya da typedef (içerir using Açıklamalar) Derlemenizin sonuçlarını açıklar. Referans çöküşünün c ++ 11'e eklenmesi gerektiğinden, aksi halde A & & gibi referanslar kullanıldığında hata olur.


6
2017-10-03 07:28



Bir "evrensel referans" durumunda referans çöküşü gerçekleşirken, gerçek sihir bu adımdan önce gerçekleşir ve şablon argümanı indirimi sırasında ortaya çıkar. Normal bir işlevde çalışmayan referans daraltma hakkındaki notunuz yanlıştır; referans çöküşü her yerde olabilir: using T = int&&; void foo(T& x); burada x bir int& referans çökmesi nedeniyle. - Simple
@Simple sağınıza benziyor, decltiplerin ve otomanın referans çöküşüne sahip olduğunu biliyordum, bir yazım hatası olabileceğini bilmiyordum, cevabımı değiştireceğim - aaronman