2011-10-03 8 views
14

I test il codice nello standard C++ ISO/IEC 14882-03 14.6.1/9 su Xcode 4.1 e Visual Studio 2008. Le uscite di i due compilatori sono entrambi diversi dal risultato previsto dello standard.Il risultato effettivo della risoluzione del nome nel modello di classe è diverso dallo standard C++ 03

Il codice è incollato di seguito.

#include <stdio.h> 
#include <iostream> 
using namespace std; 

void f(char); 

template <class T > void g(T t) 
{ 
    f(1); 
    f(T(1)); 
    f(t); 
} 

void f(int); 
void h() 
{ 
    g(2); 
    g('a'); 
} 

void f(int) 
{ 
    cout << "f int" << endl; 
} 


void f(char) 
{ 
    cout << "f char" << endl; 
} 


int main() { 
    h(); 
    return 0; 
} 

Come la descrizione dello standard. L'output previsto dovrebbe essere

f char 
f int 
f int 
f char 
f char 
f char 

Creare ed eseguire il codice su Xcode 4.1. L'output è il seguente. Nelle impostazioni di compilazione, ho provato a cambiare il "Compiler per C/C++/Object-C" per essere Apple LLVM Compiler 2.1, Gcc 4.2 e LLVM GCC 4.2. Le uscite sono le stesse.

f char 
f char 
f char 
f char 
f char 
f char 

Costruire ed eseguire il codice su Microsoft Visual Studio 2008. L'output è il seguente.

f int 
f int 
f int 
f int 
f char 
f char 

La descrizione (14.6.1/9) della norma è incollata di seguito.

Se un nome non dipende da un parametro di modello (come definito in 14.6.2), una dichiarazione (o un insieme di dichiarazioni) per tale nome deve essere nel campo di applicazione nel punto in cui il nome appare nel definizione del modello; il nome è legato alla dichiarazione (o dichiarazione) trovata in quel punto e questo legame non è influenzato dalle dichiarazioni che sono visibili nel punto di istanziazione. [Esempio:

void f(char); 
template<class T> void g(T t) 
{ 
f(1); // f(char) 
f(T(1)); // dependent 
f(t); // dependent 
dd++; // not dependent 
} 
void f(int); 
double dd; 
void h() 
{ 
// error: declaration for dd not found 
g(2); // will cause one call of f(char) followed // by two calls of f(int) 
g(’a’); // will cause three calls of f(char) 

-end esempio]

Il codice è ben formata per compilatori, ma le uscite sono diversi. Sarebbe molto pericoloso portare questo codice su piattaforme diverse.

Qualcuno ha il motivo per cui questi compilatori non seguono lo standard?

Modifica il 10/11/2011

Per http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#197, l'esempio nello standard è sbagliato. Verifica il codice qui sotto su Clang e Gcc.

#include <stdio.h> 
#include <iostream> 
using namespace std; 

void f(char); 

template <class T > void g(T t) 
{ 
    f(1); 
    f(T(1)); 
    f(t); 
} 

enum E{ e }; 

void f(E); 
void h() 
{ 
    g(e); 
    g('a'); 
} 

void f(E) 
{ 
    cout << "f E" << endl; 
} 

void f(char) 
{ 
    cout << "f char" << endl; 
} 

int main() { 
    h(); 
    return 0; 
} 

L'uscita come previsto.

f char 
f E 
f E 
f char 
f char 
f char 

Grazie,

Jeffrey

+2

+1 per la prima grande domanda –

+0

È interessante notare che Clang 2.9 sembra avere lo stesso problema di gcc. –

risposta

3

Come osservato nel primo esempio, questo è un esempio di ricerca di nome bifase, che sia GCC e Clang attuare ma MSVC non. E in questo caso, sia GCC che Clang sono corretti: in realtà è lo standard che è sbagliato, come notato in C++ core defect report #197. Lo standard C++ 11 contiene un esempio diverso.

Questo è uno dei most common problems vediamo quando il porting del codice a Clang sia da MSVC (che non ha mai implementato ricerca del nome a due fasi) o da GCC (che non ha attuato ricerca del nome a due fasi in modo uniforme fino a poco tempo).

2

non so cosa dirti se non che sono d'accordo con te che questo è un comportamento corretto.

Penso che quello che probabilmente sta succedendo è che nel caso di MSVC, il compilatore sta ottimizzando un passaggio extra al costo di finire con la conoscenza di una funzione definita successivamente che non dovrebbe essere usata nel caso di non -templa le chiamate. Devo confessare che non capisco come GCC/LLVM finirebbe con i risultati che fanno, in quanto i risultati sono quelli che ci si aspetterebbe dall'eccezione e non dalla regola.

immagino che avrei File come un bug su http://bugreport.apple.com/ e http://connect.microsoft.com/ e vedere quello che dicono?

+0

Grazie, Mahmoud. Per favore, tienimi aggiornato se c'è qualche commento. – Jeffrey

+1

@Jeffrey: Penso che suggerisse di archiviare il bug. :) –

+0

g ++ 4.6.1 presenta lo stesso comportamento di Xcode (che ha il relativamente antica g ++ 4.2), quindi per favore un bug report a http://gcc.gnu.org/bugzilla/ pure. – zwol

5

Quello che stai incontrando è il fatto che Visual Studio non implementa two-phase lookup. Esaminano solo il nome effettivo quando si crea un'istanza del modello.

E Microsoft ha deciso a questo punto che non sono interessati a supportare la ricerca in due fasi.

+0

MSVC è una causa persa, tuttavia sono sorpreso che gcc e Clang si sbagliano. –