Masalah penyusun C ++ dengan struct di kelas templat

13

Kode berikut tidak dikompilasi dengan gcc atau dentang.

template<class T>
class foo{};

template<class T>
class template_class_with_struct
{
    void my_method() {
        if(this->b.foo < 1);
    };

    struct bar
    {
        long foo;
    } b;
};

Pesan kesalahan adalah

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);

Kesalahan ini disebabkan oleh templat class foo. Saat menulis <= bukannya <1 juga mengkompilasi.

Ada petunjuk yang dihargai?

Tautan CompilerExplorer https://godbolt.org/z/v6Tygo

123tv
sumber
7
Saya akan mengatakan bug penyusun tetapi msvc adalah satu-satunya yang menerimanya: - / Demo . Kemungkinan Bekerja di sekitar b.bar::fooatau kurung ( (this->b.foo) < 1)
Jarod42

Jawaban:

1

Di GCC, saya mengerti

so.cpp:8:27: error: expected '>'
    if(this->b.foo < 1) 
                      ^

Jadi, kompiler berpikir bahwa foopada baris itu merujuk ke kelas di fooatas dan mengharapkan argumen templat. Ini mirip dengan apa yang Anda lihat.

Ketika Anda mengubahnya ke <=, yang tokenized oleh lexer sebagai token tunggal. Tahap selanjutnya bahkan tidak melihat a <, jadi tidak bingung olehnya.

Jika Anda mengubah kelas untuk tidak memiliki nama yang sama dengan yang lama bar, maka tidak memiliki masalah ini. @ Jarod42 juga memiliki saran dalam komentarnya untuk pertanyaan Anda (lebih banyak kualifikasi atau parens).

Kompiler ditulis dalam tahap, di mana setiap tahap menerjemahkan kode ke representasi yang lebih baik untuk selanjutnya, dan setiap tahap dapat melakukan hal-hal yang semakin kompleks dengan representasi itu.

Pada awalnya, kompiler "lexes" kode, yang mengubah karakter individu dalam file menjadi aliran token - itu akan melihat baris ini sebagai sesuatu seperti

// if(this->b.foo < 1) 
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)

Dan kemudian sampai ke foo. Mungkin harus dilakukan

- name(foo)
- operator(<)
- number(1)
- right-paren

Tapi, bagi saya itu terlihat seperti ketika dilihat foo, terlihat di depan, melihat <dan fakta yang foo<class T>ada dan mencoba membuat satu token dari foo< ...tetapi kemudian tidak dapat menemukan >untuk menyelesaikannya.

Ini hanya dugaan - itu bisa menjadi tahap melewati lexer yang mencoba mencari nama dan dapat menggabungkan token. Bagaimanapun, berbagai penggunaan foo menipu itu.

Lou Franco
sumber
Saya mengerti penjelasan Anda, tetapi tidak yakin apakah itu berarti kompiler harus berperilaku seperti itu. Mungkin ini harus berupa bug untuk kompiler yang berbeda. Terkadang Anda tidak dapat mengetahui kelas templat apa yang ada di dalam tajuk pustaka yang ditautkan (nama umum seperti cnt, count, counter ...)
eactor
Saya pikir ini bug, tapi saya tidak tahu apa yang dikatakan oleh spec. Memiliki nama dari header pihak ketiga menyebabkan masalah adalah kejadian umum di C ++ - Anda biasanya dapat menyelesaikannya dengan kualifikasi.
Lou Franco