Clang, bir sınıf şablonunun iç içe sınıfının yalnızca uzmanlıklar aracılığıyla tanımlandığı kodu reddetmek için doğru mu?


17

Aşağıdaki sınıf şablonu verildiğinde:

template<typename T>
struct Outer
{
    struct Inner;

    auto f(Inner) -> void;
};

Innerher uzmanlık alanı için ayrı ayrı tanımlarız Outer:

template<>
struct Outer<int>::Inner {};

template<>
struct Outer<double>::Inner {};

ve ardından aşağıdaki ftüm uzmanlıklar için üye işlevini bir kez tanımlayın Outer:

auto Outer<T>::f(Inner) -> void
{

}

ancak Clang (9.0.0) şikayet ediyor:

error: variable has incomplete type 'Outer::Inner'

auto Outer<T>::f(Inner) -> void

                      ^

InnerDiğer tüm uzmanlıkların tanımını da yaparak derleyici hatasını atlatabiliriz Outer:

template<typename T>
struct Outer<T>::Inner {};

veya fher uzmanlık için ayrı ayrı tanımlayarak :

template<>
auto Outer<int>::f(Inner) -> void
{

}

template<>
auto Outer<double>::f(Inner) -> void
{

}

Hem GCC hem de MSVC, soruyu soran ilk kodu kabul eder; Bu bir Clang hatası mı yoksa üçü arasında tek uygun uygulama mı?

Derleyici Gezgini'ni deneyin


İç uzmanlıkları önemsizdir, çıkarılması derleme sonucunu değiştirmez.
n. 'zamirler' m.

@ n.'pronouns'm. Neyi kastettiğinden emin değilim. Hem bir tanımını ekleyerek Innertüm diğer uzmanlık için ve tanımlayan fher uzmanlık için ayrı ayrı kararlılığı derleme hatası.
15'te invexed

Tekrar okuyalım: Bunları kaldırmak derleme sonucunu değiştirmez . Ekleme, kaldırma. gcc clang
n. 'zamirler' m.

@ n.'pronouns'm. Şimdi ne demek istediğini anlıyorum, ama bu hala garip bir yorum. Benim sorum, sağlanan Innerher uzmanlık için tanımlara rağmen eksik bir tür olarak raporlanmasıydı Outer. InnerTanım (lar) ını kaldırırsanız açıkça (doğru olarak) eksik bir tür olacaktır.
15'te invexed

"Açıkça Inner (doğru), tanım (lar) ını kaldırırsanız eksik bir tür olacaktır." Hayır "hiç bir şekilde ckear değil. Bir uzmanlık tamamen ayrı bir şablon ve ana şablonu hiç etkilemez.
n. 'zamirler'

Yanıtlar:


4

Clang'ın kodunuzu reddetmesinin yanlış olduğuna inanıyorum. Kendimize sormalıyız, işlev beyanınız ve tanımınız

auto f(typename T::Inner) -> void;

// ...

template<typename T>
auto Outer<T>::f(typename T::Inner) -> void
{ }

Bu örnekte, T::Inneraçıkça bağımlı bir türdür. Dolayısıyla Clang, somutlaştırılana kadar eksik olduğunu varsaymayabilir. Aynısı örneğiniz için de geçerli mi? Öyle derim ki. Çünkü bu standartta var:

[Temp.dep.type]

5 Bir isim bir olan akım örnekleme üyesi Eğer öyleyse

  • Yukarı bakıldığında, mevcut örnekleme ya da onun bağımlı olmayan bir temel sınıfı olan bir sınıfın en az bir üyesini ifade eden niteliksiz bir isim. [Not: Bu yalnızca sınıf şablonunun tanımıyla çevrelenen bir kapsamda bir ad ararken görülebilir. - son not]
  • ...

Bir ad, bakıldığında, geçerli örnekleme olan bir sınıfın en az bir üyesini ifade eden geçerli örneklemenin bir üyesi ise, geçerli örneklemenin bağımlı bir üyesidir.

9 Bir tür,

  • ...
  • bilinmeyen bir uzmanlığın üyesi,
  • geçerli somutlaştırmanın bağımlı bir üyesi olan iç içe bir sınıf veya numaralandırma,
  • ...

Yani 9. paragraftaki ilk kurşun davayı kapsıyor typename T::Inner . Bu bağımlı bir tür.

Bu arada davanız ikinci mermi ile kaplıdır. Outer::Innerşu anki örneğinde bulunan bir isimdir Outer, ayrıca içinde bulunurOuter temel sınıfta değil kendi . Bu onu mevcut örneklemenin bağımlı bir üyesi yapar. Bu ad, iç içe bir sınıfa karşılık gelir. Bu, ikinci mermideki tüm koşulların geçerli olduğu, böyleceOuter::Inner bağımlı bir tür !

Her iki durumda da kendimize bağımlı bir tipe sahip olduğumuzdan, derleyiciler onlara eşit tipte olarak davranmalıdır. Sonuç olarak GCC ve MSVC haklı.


Hata bildirildi . Teşekkürler.
8'de invexed
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.