Neden 'şablon' anahtar kelime burada gereklidir?


9

Takip koduna sahibim:

template <typename TC>
class C
{
    struct S
    {
        template <typename TS>
        void fun() const
        {}
    };

    void f(const S& s)
    {
        s.fun<int>();
    }
};

// Dummy main function
int main()
{
    return 0;
}

Bunu hem gcc 9.2 hem de clang (9.0) ile oluştururken, templateanahtar kelimeyi çağırmak için gerekli olması nedeniyle bir derleme hatası alıyorum fun. Clang şovları:

error: use 'template' keyword to treat 'fun' as a dependent template name
        s.fun<int>();
          ^
          template 

Derleyicinin funbağlam bağlamında neden bağımlı bir isim olduğunu düşündüğünü anlamıyorum f, çünkü fbir şablon değil. CBir şablon yerine normal bir sınıf olarak değiştirirseniz , hata gider; Orada beri ilk etapta bir hata olması ne neden Ancak görmüyorum Sne de fbağlıdır TC.

İşin garibi, MSVC 19.22 bunu gayet iyi derliyor.


Not

"Dupe " ve "typename" anahtar kelimelerini nereye ve neden koymalıyım? lütfen Sbunun gerçekten bağımlı bir isim olsa bile , bağlamında fmevcut örneğe üye olmaları olmasa bile bağımlı olmayacağı özel bir durum olduğunu düşünün .


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Bhargav Rao

Yanıtlar:


10

Şunları düşünün :

template<typename T>
struct C
{
    struct S
    {
        int a = 99;
    };

    void f(S s, int i)
    {
        s.a<0>(i);
    }
};

template<>
struct C<long>::S
{
    template<int>
    void a(int)
    {}
};

int main()
{
    C<int>{}.f({}, 0); // #1
    C<long>{}.f({}, 0); // #2
}

s.a<0>(i)iki karşılaştırma işlemlerinin ihtiva eden bir ifade olarak ayrıştırılır <ve >ve bu 1. için iyi ama 2. için başarısız olur.

Bu ise değişmiş için s.template a<0>(i)daha sonra 2. sakınca ve 1. başarısız olur. Böylece templateanahtar kelime burada asla gereksiz değildir.

MSVC olan yetenekli ifadeyi yorumlama s.a<0>(i)aynı program çerçevesinde her iki yönde. Ancak bu standarda göre doğru değildir; her ifadenin derleyicinin ilgilenmesi için yalnızca bir ayrışması olmalıdır.


Bunu hala tam olarak anlamıyorum. Örneğiniz, bu durumda ya uzmanlaşmayı Cya da diğerini kullandığınızı gösterir, ancak ikisini birden başlatamazsınız. Buradaki templateanahtar kelime hala gereksiz IMHO'dur, çünkü hangisinin seçileceği hangisini başlattığınıza Sbağlıdır C. templateAnahtar kelime olmadan her ikisini de başlatabilirsiniz ve f'nin davranışı her örnek için farklı olur.
Martin

2
@Martin, her token'ın kaynak dosyada sadece bir sözdizimsel rolü olması gerektiğidir. Örneğin, <simgenin bir şablon örneğinde bir karşılaştırma operatörü ve başka bir örneklemede bir açılış açısı braketi olması uygun değildir. Bu, derleyicilerin bir AST'ye (şablon türleri için yer tutucularla) şablonları ayrıştırabilmesini sağlamak içindir.
ecatmur

Mantıklı. Teşekkürler!
Martin

7

funöğesinin şablon parametresine bağlı olarak bir şablon işlevi olabilir veya olmayabilir (veya hiç olmayabilir) class C.

Çünkü uzmanlaşabilirsiniz S(uzmanlaşmadan C):

template <> struct C<int>::S {};

Derleyici funilk bakıldığında class C(template parametresini değiştirmeden önce) şablon olup olmadığını bilmek ister template, gereklidir.


1
zihin ... şişmiş ...
bolov

Bunun takibi, bu yeni tanımlara Shiç erişilip erişilemeyeceğidir f. Eğer yapamazlarsa, bu kısıtlamaya sahip folmak mantıklı değildir, çünkü onları yine de göremezsiniz.
Martin

@Martin Hem GCC, Clang hem de MSVC ile fbunu bulur.
HolyBlackCat

@bolov Evet, birçok farklı konuda uzmanlaşabilirsiniz .
HolyBlackCat
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.