2013-12-18 13 views
18

Nel seguente codice C++ 11:Inizializzatore C++ 11 con funzione id-espressione ambigua?

void f(int) {} 
void f(double) {} 

void (*p)(int) = f; 

Ci sono due funzioni.

Il terzo identificatore f è un'espressione id e l'inizializzatore di p.

In 5.1.1p8 [expr.prim.general]/8 si legge:

Il tipo di [id-espressione] è il tipo di identificatore. Il risultato è l'entità denotata dall'identificatore. Il risultato è un lvalue se l'entità è una funzione, una variabile o un membro dati e un valore diverso altrimenti.

Dato che f potrebbe riferirsi a due soggetti diversi con due tipi differenti, non c'è "l'entità" o "tipo".

C'è qualche altro testo nello standard che risolve questa situazione?

Le implementazioni non sono altro che una disambiguazione come estensione o sono richieste da qualche parte? (. Senza qualche altro testo si potrebbe sostenere che un'implementazione potrebbe rifiutare la f id-espressione ambigua)

+0

Non ho prove, ma io * penso * questo non è ambiguo. Considera cosa succede quando una funzione sovraccaricata è ** chiamata. ** 'f (T1)' vs. 'f (T2)'. Qui, il compilatore dovrebbe decidere quale funzione (puntatore) deve chiamare. IMO questo è un caso simile. (e +1, finalmente una buona domanda sul C++!) –

+0

Questo è richiesto dallo standard, ma non ricordo il testo che lo tratta. Fammi cercare. – Nawaz

+0

@ DietmarKühl Bene, questo è quello che sto dicendo ... –

risposta

17

Lo standard (al § 13.4) definisce che:

Un uso di un nome funzione sovraccaricata colpo gli argomenti sono risolti in determinati contesti di una funzione, un puntatore alla funzione o un puntatore alla funzione membro per una funzione specifica dal set di sovraccarico. Un nome di modello di funzione viene considerato per denominare un set di funzioni sovraccaricate di in tali contesti. La funzione selezionata è quella il cui tipo è identico al tipo di funzione del tipo di destinazione richiesto in il contesto.

Enfasi mia.

Dopo la citazione, c'è un esempio (al § 13,4/5) che assomiglia vostra:

int f(double); 
int f(int); 
int (*pfd)(double) = &f; // selects f(double) 
int (*pfi)(int) = &f; // selects f(int) 

Per quanto riguarda la unaria & è interessato, la norma specifica che (§ 5.3 .1/6 e grazie a jogojapan):

l'indirizzo di una funzione sovraccaricata può essere presa solo in un contesto che determina univocamente quale versione della funzione overload è a cui si fa riferimento.

ma può anche essere omessa (al § 13,4/1):

Il nome della funzione overload può essere preceduta dall'operatore &.

(di nuovo, enfasi mia) proprio come hai fatto tu, nel tuo esempio.

+0

Buono, in una singola frase questo spiega anche come funziona nelle chiamate di funzione e con' static_cast'! –

+1

+1. Grande citazione. :-) – Nawaz

+0

Sicuramente la risposta giusta. Si potrebbe voler aggiungere un riferimento alla 5.3.1/6, che chiarisce che un'applicazione dell'operatore di indirizzo è uno dei "determinati contesti". (Anche se gli esempi citati potrebbero renderlo chiaro). – jogojapan