2016-04-15 11 views
7

La detrazione per f1 e f2 non è corretta?Detrazione argomenti modello per pacchetto parametri funzione seguito da altri parametri

template<class... T, class U> 
void f1(T..., U){} 

template<class... T> 
void f2(T..., int){} 

int main() 
{ 
    f1(1); 
    f2(1); 
    return 0; 
} 

g ++ accetta sia, clang accetta solo f2, e msvc respinge entrambi.

Related formulazione standard:

[temp.deduct.call]

Quando un parametro funzione pack appare in un contesto non-dedotta ([temp.deduct.type]), il tipo di quel parametro pack è mai dedotto .

[temp.deduct.type]p5

I contesti non dedotta sono:

  • Un parametro pacchetto funzione che non si verifica alla fine del parametro di dichiarazione-list.

Quindi sembra che MSVC sia corretto nel respingere entrambi?

Significa che qualsiasi istanziazione dei modelli sarà mal formata, anche se si specifica esplicitamente il modello args?

f1<int>(1, 2); // ill-formed? 
f2<int>(1, 2); // ill-formed? 

Se questo è il caso, perché consentire tali dichiarazioni al primo posto?

risposta

2

C'è un DR per questo numero specifico DR1388. A parte questo, sembra che GCC e CLANG non l'abbiano ancora implementato CLANG DR1388.

Vuol dire che qualsiasi istanza di modelli sarà mal formati, anche se si specifica args modello esplicitamente?

f1<int>(1, 2); // ill-formed? 
f2<int>(1, 2); // ill-formed? 

Se questo è il caso, perché consentire tali dichiarazioni al primo posto?

No se si specificano esplicitamente gli argomenti del modello, non si verifica alcuna detrazione e, come tale, il codice mostrato sopra è legale.

+0

Credo che la risoluzione è ancora imperfetta - un pacchetto di parametri è concettualmente infinito, non è possibile specificare esplicitamente * tutti * gli argomenti, il che significa che è sempre necessario dedurre i parametri e poiché si trova in un contesto non dedotto, il resto del pacchetto di parametri non viene mai dedotto. – Jamboree

+0

@Jamboree Hai detto tu stesso "è un contesto non dedotto", tuttavia se specifichi esplicitamente gli argomenti del pacchetto non si verifica alcuna deduzione. – 101010

+0

Sono considerati esplicitamente specificati: 'f1 <> (1); f2 <> (1); '? '' <> Fa qualche differenza qui? – Jamboree

0

Ho esaminato esattamente questa domanda e ho trovato sorprendentemente difficile ottenere una risposta chiara. Come meglio posso dire, f1(1) dovrebbe essere rifiutato ma f2(1) deve essere accettato.

Detto:

  • clang ++ - 5.0 accetta sia
  • g ++ - 6 accetta sia
  • EDG 4.14 scarti sia

Come lei ha sottolineato, un parametro di funzione pack che non si verifica alla fine della lista è un contesto non dedotta ([temp.deduct.type] p5):

I contesti non dedotta sono: parametro pacchetto

  • ...
  • Una funzione che non si verifica alla fine del parametro di dichiarazione-list.

e [temp.deduct.call] p1 (modificato tramite CWG 1388) chiarisce che tale parametro pack è mai dedotto.

Quando un pacchetto di parametri di funzione viene visualizzato in un contesto non dedotto, il tipo di quel pacchetto di parametri non viene mai dedotto.

Inoltre, [temp.arg.explicit] p3 specifica:

Un parametro di modello finale pacco (14.5.3) non altrimenti dedotta verrà dedotta a una sequenza vuota di argomenti del template.

così, tenendo conto di questo per la chiamata f2(1): il pacco T è un trascinamento parametro pacco modello (anche se non è un trascinamento funzione parametrica pacchetto), quindi dedotta da un pacchetto vuoto e la chiamata è valida

Tuttavia, per f1(1), il pacchetto T non è un parametro di parametri del modello finale poiché è seguito da U, pertanto non si presuppone che sia un pacchetto vuoto per [temp.arg.explicit] p3. Pertanto, poiché il parametro template pack T non può essere dedotto per la chiamata a f1(1), non dovrebbe prendere parte alla risoluzione di sovraccarico e la chiamata dovrebbe fallire.


Si noti che alcune domande simili/esempi sono stati portati in altre discussioni, ma che presentano alcune piccole differenze:

  • Il f(0) chiamata nel codice di esempio di CWG 1388 e CWG 1399 è valido perché il pacchetto in questione è un pacchetto di parametri del template finale, quindi ricade nel caso che ho menzionato sopra. Ecco il codice da CWG 1399:
    template <class... T> 
    void f(T..., int, T...) { } 
    
    int main() { 
        f(0);   // OK 
        f<int>(0,0,0); // OK 
        f(0,0,0);  // error 
    } 
    
  • Il codice di esempio nella discussione di LLVM bug 21774 è simile all'esempio CWG 1399, il pacchetto è un pacchetto parametro di modello finale. Allo stesso modo per questo question.
  • CWG 2055, che non è risolto, tocca un caso simile. Ogni volta che viene risolto, la sua risoluzione probabilmente farà luce sul comportamento corretto degli esempi in questa domanda.Ecco la questione di cui al CWG 2055:

    Non è chiaro che [l'attuale formulazione dello standard] permette un esempio come:

    template<typename... T> void f(typename T::type...) { 
    } 
    
    int main() { 
        f<>(); 
    } 
    
Problemi correlati