Neden enjekte edilmiş bir sınıf adı var?


150

Son zamanlarda garip bir C ++ özelliği gördüm: enjekte edilen sınıf adı .

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

Ancak bu özelliğin neden gerekli olduğunu anlayamıyorum. Bu özelliği gerektiren herhangi bir uygulama var mı?

Ve bu özelliğin eski C ++ 'da olmadığını duydum. O halde ne zaman tanıtıldı? C ++ 03? C ++ 11?

Yanıtlar:


166

Enjekte edilen sınıf adı X, üyesi olarak bildirilen anlamına gelir X, böylece içerideki ad araması Xher zaman geçerli sınıfı bulur X, aynı kapsama alanında bildirilmiş olabilecek başka bir sınıf değil , örn.

void X() { }
class X {
public:
  static X create() { return X(); }
};

Is create()fonksiyonu geçici oluşturarak Xnesne veya işlevini çağırarak X? Ad alanı kapsamında işlevi çağırır, bu nedenle enjekte edilen sınıf adının amacı X, adın gövdesi içinde her zaman sınıfın kendisini bulmasını sağlamaktır (çünkü ad araması, kapsama bakmadan önce sınıfın kendi kapsamında başlar. dürbün).

Ayrıca, enjekte edilen sınıf adının bir şablon bağımsız değişken listesi olmadan kullanılabildiği, örneğin Footam şablon kimliği yerine basitçe kullanarak Foo<blah, blah, blah>, mevcut somutlaştırmaya başvurmak kolay olan sınıf şablonlarının içinde de yararlıdır . Bunu açıklığa kavuşturan C ++ 98 ve C ++ 03 arasında bir değişiklik için DR 176'ya bakın .

Enjekte edilen sınıf adı fikri C ++ 98'de mevcuttu, ancak terminoloji C ++ 03 için yeniydi.

C ++ 98 diyor ki:

Sınıf adı görüldükten hemen sonra bildirildiği kapsama bir sınıf adı eklenir . Sınıf adı da sınıfın kendi kapsamına eklenir.

İkinci cümle DR 147 tarafından değiştirildi, bu nedenle C ++ 03 [class] / 2'de şunu söylüyor:

Sınıf adı görüldükten hemen sonra bildirildiği kapsama bir sınıf adı eklenir . Sınıf adı da sınıfının kendi kapsamı içine yerleştirilir; bu, enjekte edilen sınıf adı olarak bilinir .

C ++ 98'den önce bile, ARM kabaca eşdeğer bir ifadeye sahiptir; bu, sınıfın adının sınıf gövdesinde sınıfın kendisine başvurmak için her zaman kullanılabileceği anlamına gelir:

Bir sınıfın adı , sınıf belirticisinin üye listesinde bile bir sınıf adı olarak kullanılabilir .

  • Örneğin,

    class link { link* next; };


2
Oldukça sık soruldu, ancak sorunu gösteren basit bir örnek asla oluşturamadı. Yani +1 Örnek için.
dhein

1
Bu, clang ++ your_program.cpp -Xclang -ast-dump çalıştırırsanız ve sınıfınızı ve ardından enjekte edilmiş bir sınıf alt düğümünü görürseniz açıkça görülebilir.
xaxxon
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.