Problema del compilatore C ++ con struct in classe modello


13

Il codice seguente non viene compilato con gcc o clang.

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;
};

Il messaggio di errore è

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

L'errore è causato dalla classe templat pippo. Quando si scrive <= anziché <1, viene compilato anche.

Qualche suggerimento apprezzato?

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


7
Direi bug del compilatore ma msvc è l'unico ad accettarlo: - / Demo . Possibili soluzioni b.bar::fooo parentesi ( (this->b.foo) < 1)
Jarod42

Risposte:


1

Nel GCC, ottengo

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

Quindi, il compilatore pensa che foosu quella riga si riferisca alla classe foosopra e si aspetta un argomento template. Questo è simile a quello che stai vedendo.

Quando lo cambi in <=, che viene tokenizzato dal lexer come un singolo token. La fase successiva non vede nemmeno un <, quindi non è confusa da esso.

Se cambi la classe in modo che non abbia lo stesso nome del long in bar, allora non ha questo problema. Inoltre, @ Jarod42 ha suggerimenti nel suo commento alla tua domanda (più qualifiche o parentesi).

I compilatori sono scritti in più fasi, in cui ogni fase traduce il codice in una rappresentazione migliore per la successiva e ogni fase può fare cose sempre più complesse con quella rappresentazione.

All'inizio, il compilatore "allenta" il codice, che trasforma i singoli caratteri nel file in un flusso di token: vedrebbe questa riga come qualcosa di simile

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

E poi arriva al foo. Probabilmente dovrebbe fare

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

Ma a me sembra che quando vede foo, guarda avanti, vede il <e il fatto che foo<class T>esiste e cerca di ricavarne un singolo token foo< ...ma non riesce a trovarlo >per completarlo.

Questa è solo una supposizione: potrebbe essere una fase oltre il lexer che cerca di trovare nomi e può combinare token. In ogni caso, i molteplici usi di foo lo stanno ingannando.


Comprendo la tua spiegazione, ma non sono sicuro che ciò significhi che il compilatore dovrebbe comportarsi in questo modo. Forse questo dovrebbe essere un campo come bug per i diversi compilatori. A volte non si può essere consapevoli di quali classi di template si trovano all'interno di un'intestazione di libreria collegata (nomi comuni come cnt, count, counter ...)
eactor

Penso che sia un bug, ma non so cosa dice la specifica. Avere nomi da intestazioni di terze parti causa problemi è un evento comune in C ++ - di solito è possibile risolvere con la qualifica.
Lou Franco,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.