Ciò non riesce a causa della ricerca di nomi in due fasi in C++.
Nella fase uno, quando il modello viene analizzato inizialmente, molto prima che sia istanziato, il compilatore analizza il modello e cerca eventuali nomi non dipendenti. S::P
è un nome non dipendente, quindi il compilatore tenta di cercarlo, ma fallisce perché è privato.
Nella fase 2, quando il modello viene istanziato, il compilatore cerca qualsiasi nome dipendente, che può variare da modello a modello.
Clang è abbastanza strettamente conforme alla ricerca del nome in due fasi. Tuttavia, MSVC ha un modello di parsing template che ritarda quasi ogni ricerca al tempo di istanziazione, che fa parte della fase 2. Questo ritardo è il motivo per cui il tuo esempio verrebbe compilato con MSVC (che non è conforme) e non in clang. Ecco un link con ulteriori informazioni:
The Dreaded Two-Phase Name Lookup
Inoltre, qui sezioni dallo standard C++ dove si descrive la ricerca in due fasi.
14.6.8:
Quando si cerca per la dichiarazione di un nome usato in una definizione di modello , le regole usuali di ricerca (3.4.1, 3.4.2) vengono utilizzati per nomi non dipendenti . La ricerca dei nomi che dipendono dai parametri del modello viene posticipata fino a quando non si conosce l'argomento del modello effettivo.
14.6.9:
Se il nome non dipende da un modello di parametri (come definito nella 14.6.2), una dichiarazione (o una serie di dichiarazioni) per tale nome deve essere nel campo di applicazione nel punto in cui il nome appare nella definizione del modello ; il nome è associato alla dichiarazione (o alle dichiarazioni) trovata in quel punto e questa associazione non è influenzata dalle dichiarazioni che sono visibili nel punto di istanziazione.
Poi la parte di 3.4 nomi di ricerca applicabile a voi:
Le regole di accesso (clausola 11) sono considerati solo una volta la ricerca dei nomi e risoluzione funzione di sovraccarico (se applicabile) sono riusciti. Solo dopo la ricerca del nome, la risoluzione di sovraccarico della funzione (se applicabile) e il controllo dell'accesso sono riusciti gli attributi introdotti dalla dichiarazione del nome utilizzata ulteriormente nell'elaborazione di espressioni (clausola 5).
È chiaro dalla lettura di queste parti che il programma è mal formato. L'unica cosa che gli stati standard dovrebbero essere rinviati fino alla creazione di istanze è la ricerca di un nome dipendente. I nomi non dipendenti passano attraverso la normale ricerca del nome, che include le regole di accesso.
Cosa, esattamente, pensi di "fare affidamento"? Il modello non può essere istanziato. –
Il codice che sto osservando (ma non ha scritto) utilizza il fatto oscuro che MSVC consente al compilatore di compilare il modello non valido per applicare restrizioni sui tipi passati in altri modelli. Quando viene passato un tipo non valido, viene utilizzato un sovraccarico che utilizza questo modello, causando un errore di compilazione. – brendanw
@brendanw: anche il front-end EDG non dà alcun errore. –