2015-07-13 4 views
8

Su gcc 4.9.0:Prendendo l'indirizzo di una funzione di modello sovraccarico è possibile, a volte

#include <iostream> 
#include <map> 

struct A 
{ 
    typedef int type; 
}; 

template<typename T> void foo(T*) { std::cout << "a" << std::endl; } 
template<typename T> void foo(typename T::type*) { std::cout << "b" << std::endl; } 

template<typename T> 
struct identity 
{ 
    typedef T type; 
}; 

template<typename T> void bar(T*) { std::cout << "a" << std::endl; } 
template<typename T> void bar(typename identity<T>::type*) { std::cout << "b" << std::endl; } 

int main() 
{ 
    //auto f = foo<A>; // ambiguous 
    foo<A>(0); // prints "b", as the second overload is more specific 

    auto b = bar<A>; // fine 
    bar<A>(0); // prints "b", as the second overload is more specific (?) 
    b(0); // prints "b" 

    return 0; 
} 

Qualsiasi indizio sul motivo per cui l'indirizzo può essere assunto, nel secondo caso?

+0

Clang rifiuta entrambi i casi. –

+0

g ++ 4.9.0 sembra accettare il secondo – gd1

+0

@ T.C., G ++ 4.9.2 compila il codice e produce l'output che corrisponde alla descrizione dell'OP. –

risposta

3

La detrazione per auto è uguale alla deduzione del modello. Da [dcl.spec.auto]:

Quando una variabile dichiarata utilizzando un tipo di segnaposto viene inizializzato, [...], il tipo di ritorno dedotto o tipo di variabile è determinata dal tipo del suo inizializzatore. Se il segnaposto è l'identificatore automatico del tipo, il tipo dedotto viene determinato utilizzando le regole per la deduzione degli argomenti del modello. Se il segnaposto è lo autoidentificatore di tipo, , il tipo dedotto viene determinato utilizzando le regole per la deduzione degli argomenti del modello.

Così, quando abbiamo uno:

auto f = foo<A>; 
auto b = bar<A>; 

Stiamo eseguendo tipo deduzione come se abbiamo chiamato (per prendere in prestito la scelta di TC di parole):

template <typename M> void meow(M); 
meow(foo<A>); 
meow(bar<A>); 

e utilizzando la dedotta digitare M come il tipo di f e b, rispettivamente.

Ma, secondo [temp.deduct.type], l'enfasi è mia:

Se un parametro di modello viene utilizzato solo nei non-dedotta contesti e non è esplicitamente specificato, la deduzione modello di argomentazione fallisce.

I contesti non dedotta sono:
- [...]
- Un parametro funzione per la quale la deduzione argomento non può essere fatto perché la funzione associata argomento è una funzione o un insieme di funzioni sovraccaricate (13.4), e uno o più dei seguenti casi:
        - più di una funzione corrispondente al tipo di parametro di funzione (con un conseguente detrazione ambiguo), o
        - nessuna funzione corrisponde al tipo di parametro funzione o
        - l'insieme delle funzioni fornite come argomento contiene uno o più modelli di funzione.
- [...]

In entrambi i casi, l'argomento è un insieme di funzioni sovraccaricate che contiene uno o più modelli di funzione - che lo rende un contesto non dedotto, in modo da modello detrazione argomento non. Quindi, clang è corretto nel respingere entrambe le inizializzazioni.

+0

Questo è difficile. Sono incline a pensare che [temp.deduct.type] /5.5.1 ne faccia un contesto non dedotto, il che significa che la deduzione di 'auto' dovrebbe fallire in entrambi i casi. –

+0

@ gd1 Per una risposta più approfondita sull'ordinazione parziale, controlla [risposta di Columbo qui] (http://stackoverflow.com/a/31051322/2069064) – Barry

+0

@Barry Non sto parlando della detrazione per 'bar' (ovviamente non c'è nessuna detrazione), sto parlando della deduzione per 'auto', che è come se si fosse fatto' template void meow (M); meow (bar ); 'e deduci' M'. –

Problemi correlati