C ++ decltype ve parantezler - neden?


32

Konu daha önce tartışılmıştı , ancak bu bir kopya değil.

Birisi decltype(a)ve arasındaki farkı sorduğunda decltype((a)), normal cevap - abir değişkendir, (a)bir ifadedir. Bu cevabı tatmin edici bulmuyorum.

Birincisi, abir ifadedir. Birincil ifade seçenekleri arasında, diğerleri arasında -

  • (ifade)
  • id-ifadesi

Daha da önemlisi, decltype ifadesi parantezleri çok, çok açık bir şekilde ele alır :

For an expression e, the type denoted by decltype(e) is defined as follows:
(1.1)  if e is an unparenthesized id-expression naming a structured binding, ...
(1.2)  otherwise, if e is an unparenthesized id-expression naming a non-type template-parameter, ...
(1.3)  otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, ...
(1.4)  otherwise, ...

Yani soru kalıyor. Parantezler neden farklı muamele görüyor? Teknik belgeleri veya komite tartışmalarını bilen var mı? Parantezler için açık bir değerlendirme, bunun bir gözetim olmadığını düşünmeye neden olur, bu yüzden eksik olduğum teknik bir neden olmalı.


2
- "(a) bir ifadedir, bir bir değişkendir her zamanki cevabı" onlar demek ne " (a)bir ifadesidir ve abir ifadesidir ve değişken".
HolyBlackCat

Yanıtlar:


18

Bu bir gözetim değil. İlginçtir, Decltype ve auto'da (revizyon 4) (N1705 = 04-0145) bir ifade var:

Decltype kuralları şimdi açıkça belirtiyor decltype((e)) == decltype(e)(EWG tarafından önerildiği gibi).

Ancak Decltype'de (revizyon 6): önerilen ifadeler (N2115 = 06-018) değişikliklerden biri

Decltype içindeki parantez içinde ifade bir id-expression.

İfadede mantık yoktur, ancak bunun biraz farklı bir sözdizimi kullanarak dekltipin bir uzantısı olduğunu, başka bir deyişle, bu vakaları ayırt etmeyi amaçladığını düşünüyorum.

Bunun kullanımı C ++ taslakta gösterilir 9.2.8.4:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 17;        // type is const int&&
decltype(i) x2;                 // type is int
decltype(a->x) x3;              // type is double
decltype((a->x)) x4 = x3;       // type is const double&

Gerçekten ilginç olan, returnifadeyle nasıl çalıştığıdır :

decltype(auto) f()
{
    int i{ 0 };
    return (i);
}

Visual Studio 2019, gereksiz parantezleri kaldırmamı önerir, ancak aslında yerel bir değişkene başvuru döndürdüğünden bu yana decltype((i))dönüş değerini int&UB yapar.


Kökeni kesin olarak işaretlediğiniz için teşekkür ederiz! Decltype sadece farklı bir şekilde belirlenemezdi, başlangıçta olduğu ortaya çıktı. Rev-6 belgesi açıkça bu komik parantez davranışını ekler, ancak mantığı atlar :(. Sanırım bu, şimdi alacağımız kadar bir cevaba yakın ..
Ofek Shilon

Ve yine de hiç kimse saçma sorunu iki farklı işlev için iki ayrı anahtar kelime yaparak çözmeyi teklif etmedi mi? Komitenin en büyük hatalarından biri (tarihsel olarak pek çok zorlayıcı hata yaptı).
curiousguy

13

Parantezler neden farklı muamele görüyor?

Parantezler farklı şekilde tedavi edilmez. Farklı muamele gören şeffaf olmayan kimlik ifadesi.

Parantez bulunduğunda, tüm ifadeler için normal kurallar geçerlidir. Tür ve değer kategorisi çıkarılır ve türünde kodlanır decltype.

Özel hüküm, yararlı kodu daha kolay yazabilmemiz için var. Bir decltype(üye) değişkenin adına uygulanırken, genellikle ifade olarak işlendiğinde değişkenin özelliklerini temsil eden bir tür istemeyiz. Bunun yerine, değişkenin bildirildiği türü, ona ulaşmak için bir ton tür özelliği uygulamak zorunda kalmadan istiyoruz. Ve bu decltypebize vermek için tam olarak belirtilen şey.

Eğer biz bir ifadesi olarak değişkenin özellikleri hakkında bakım yapmak, o zaman biz yine de parantez fazladan bir çift ile oldukça kolay bir şekilde elde edebilirsiniz.


Bir Yani intüyesi iarasında a, decltype(a.i)olduğuint süre decltype((a.i))olduğunu int&(varsayarak adeğil const)? İfade a.iatanabilir olduğundan?
n314159

1
@ n314159 - Bunun özü bu. İfade a.iconst olmayan bir değerdir, bu nedenle için const olmayan bir değerlik başvuru türü alırsınız (a.i).
StoryTeller - Unlander Monica

'Tüm ifadeler için normal kurallar' neden türlerinin bir referans olduğunu gösteriyor? Neden 'değişkenin bir ifade olarak özellikleri' referans olma özelliğini içerir? Doğal bir temerrüt mü?
Ofek Shilon

1
@OfekShilon - Türleri bir referans değil. Bir ifadenin türü hiçbir zaman referans olarak analiz edilmez . Ancak dectlype sadece bir türe çözümleyebilir ve bize sadece bir ifadenin türünü değil, aynı zamanda değer kategorisini de anlatmak içindir. Değer kategorisi referans türlerine göre kodlanmıştır . Sol taraf olan &XValues vardır, &&ve prvalues referans türleri değildir.
StoryTeller - Unlander Monica

@StoryTeller tam olarak, ifade türleri ile ifade olmayanlar arasında 'doğal' bir fark yoktur. Bu ayrımı yapay yapar.
Ofek Shilon

1

C ++ 11'den önce iki farklı türde bilgi almak için dil araçlarına ihtiyacınız var :

  • bir ifadenin türü
  • bildirildiği şekliyle bir değişkenin türü

Bu bilgilerin doğası gereği, dilde özellikler eklenmelidir (bir kütüphanede yapılamaz). Bu, yeni anahtar kelimeler anlamına gelir. Standart bunun için iki yeni anahtar kelime getirebilirdi. Örneğin exprtype, bir ifadenin decltypetürünü ve bir değişkenin bildirim türünü almak için. Bu açık ve mutlu bir seçenek olurdu.

Bununla birlikte, standart komite, eski kodun bozulmasını en aza indirmek için dile yeni anahtar kelimeler sokmaktan kaçınmak için her zaman elinden geleni yapmıştır . Geriye dönük uyumluluk, dilin temel bir felsefesidir.

C ++ 11 ile iki farklı şey için kullanılan tek bir anahtar kelimemiz var: decltype . İki kullanım arasında farklılaşma şekli farklı davranmaktır decltype(id-expression). Komite tarafından bilinçli bir karardı, (küçük) bir uzlaşma.


Bunu bir cpp konuşmasında duyduğumu hatırlıyorum. Ancak kaynağı bulma umudum yok. Birisi bulursa harika olur.
bolov

1
C ++ geçmişte pek çok alt çizgi içermeyen ve bazıları İngilizce olan bir grup yeni anahtar kelime ekledi. Rasyonel gerçekten saçma.
curiousguy

@curiousguy sunulan her anahtar kelime mevcut kullanıcı sembolleriyle çakışacak, böylece komite dile yeni ayrılmış anahtar kelimeler ekleme kararına ağır ağırlık verecektir. Bu saçma imo değil.
bolov

Doğru değil: exporttanıtıldı. Sahip olabilirseniz export(önceden tüm şablonlar varsayılan olarak "dışa aktarılmıştır") decltypeve gibi şeyler olabilir constexpr. Açıkçası registerbaşka bir dilde eklemek sorun yaratacaktır.
curiousguy

@bolov Teşekkürler! (1) Bu spekülasyon veya bilgi mi? Motivasyonun fazladan bir anahtar kelimeden kaçınıldığı tartışmaların farkında mısınız? (2) "İfade olarak" kullanılıyorsa, bir id-ifadesinin gerçekten farklı muamele görmesi gereken bir örnek verebilir misiniz? (Bu ne anlama geliyor?)
Ofek Shilon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.