2013-06-14 9 views
8

esiste una tecnica che a volte uso quando si esegue l'override template funzioni che fa così:Vuoti pacchetti di enumerazioni variardici - fanno due funzioni diverse?

#include <utility> 
template<int> struct unique_enum { enum class type {}; }; 
template<int index> using UniqueEnum = typename unique_enum<index>::type; 
template<bool b, int index=1> 
using EnableFuncIf = typename std::enable_if< b, UniqueEnum<index> >::type; 
template<bool b, int index=1> 
using DisableFuncIf = EnableFuncIf<!b, -index>; 

// boring traits class: 
template<typename T> 
struct is_int : std::false_type {}; 
template<> 
struct is_int<int> : std::true_type {}; 

#include <iostream> 
// use empty variardic packs to give these two SFINAE functions different signatures: 
template<typename C, EnableFuncIf< is_int<C>::value >...> 
void do_stuff() { 
    std::cout << "int!\n"; 
} 
template<typename C, DisableFuncIf< is_int<C>::value >...> 
void do_stuff() { 
    std::cout << "not int!\n"; 
} 

int main() { 
    do_stuff<int>(); 
    do_stuff<double>(); 
} 

Ciò distingue do_stuff da do_stuff, perché si prende 0 o più UniqueEnum<1> s, e l'altro prende 0 o più UniqueEnum<-1> s. gcc 4.8 considera questi diversi pacchetti vuoti distinti.

Tuttavia, nell'ultima versione di clang che ho provato, questo non funziona: tratta la funzione con 0 UniqueEnum<1> s come la funzione con 0 UniqueEnum<-1> s.

Esistono soluzioni semplici che funzionano in clang, ma mi chiedo se la mia tecnica di cui sopra sia legale: do due funzioni template s, che differiscono solo per i pacchetti di parametri variardici vuoti, in realtà diversi?

risposta

2

Penso che GCC abbia ragione e la tua tecnica sia corretta. Fondamentalmente, poiché l'argomento di tipo per C è specificato esplicitamente, la domanda è se:

a. la sostituzione di C in qualsiasi altro punto nella firma del modello di funzione avviene prima, quindi viene eseguita la deduzione del tipo (che dovrebbe comportare un errore di sostituzione); oppure

b. la deduzione di tipo viene eseguita per prima, quindi viene eseguita la sostituzione (che non comporterebbe un errore di sostituzione, poiché il pacchetto di argomenti corrispondente sarebbe vuoto e quindi non ci sarebbe alcuna sostituzione da eseguire).

Sembra che GCC assuma (1), mentre Clang assume (2). Paragrafo 14.8.2/2 del C++ 11 specifica standard:

Quando viene specificato un elenco di modelli argomento esplicito, gli argomenti di template deve essere compatibile con la lista dei parametri modello e deve risultare in un tipo di funzione valida come descritto sotto; altrimenti digitare la detrazione non riesce. Specificamente, le seguenti operazioni vengono eseguite quando si valuta un modello lista di argomenti esplicitamente specificato rispetto ad un determinato modello di funzione:

- Gli argomenti del template specificati devono corrispondere ai parametri del modello in natura (per esempio, tipo, non-type , Modello ). Non ci devono essere più argomenti di quanti siano i parametri a meno che almeno un parametro sia un pacchetto di parametri template e ci sia un argomento per ciascun parametro non-pack. In caso contrario, la deduzione di tipo non riesce.

- Non di tipo argomenti devono corrispondere i tipi dei parametri del modello non-tipo corrispondente, oppure devono essere convertibili ai tipi di parametri non corrispondenti di tipo come specificato in 14.3.2, altrimenti tipo detrazione non riesce.

- I valori dell'argomento modello specificato vengono sostituiti ai parametri modello corrispondenti come specificato sotto.

il seguente paragrafo dice poi:

volta eseguita questa sostituzione, le regolazioni tipo di parametro funzione descritti in 8.3.5 vengono eseguite. [...]

Inoltre, comma 14.8.2/5 specifica:

I risultanti sostituito e regolato funzione tipo viene utilizzato come tipo di modello di funzione di template argomento deduzione . [...]

Infine, il paragrafo 14.8.2/6 va come segue:

In certi punti del processo detrazione modello argomento, è necessario prendere un tipo di funzione che fa uso dei parametri del modello e sostituire i parametri del modello con gli argomenti del modello corrispondente . Questa operazione viene eseguita all'inizio della deduzione degli argomenti del modello quando qualsiasi argomento modello specificato esplicitamente viene sostituito nel tipo funzione e nuovamente alla fine della deduzione argomento modello quando gli argomenti del modello che sono stati dedotti o ottenuti dagli argomenti predefiniti sono sostituiti .

Tutto ciò sembra implicare che viene eseguita la prima sostituzione, quindi la deduzione argomento modello. Quindi, in entrambi i casi si verifica un errore di sostituzione e uno dei due modelli deve essere scartato dal set di sovraccarico.

Sfortunatamente, non sembra esserci una specifica chiara su quale debba essere il comportamento quando gli argomenti dei template vengono dedotti piuttosto che essere esplicitamente specificati.

+0

Questo si applica solo quando specifichiamo esplicitamente l'argomento e non lo deduciamo? (cioè, se avessi reso la funzione prendi 'T const &', quindi passassi '7' su di esso, il trucco non sarebbe più legale?) – Yakk

+0

@Yakk: In tal caso non sono esattamente sicuro, ma ho letto attraverso l'intero 14.8.2 diverse volte e mi sembra che lo Standard non specifichi quale dovrebbe essere il comportamento –

Problemi correlati