9

Vorrei essere in grado di scrivere qualcosa in queste righe:È legale utilizzare modelli variadici nell'overloading dell'operatore?

struct bar {}; 

template <typename ... Args> 
bar operator+(bar, Args ...) 
{} 

Ho appena controllato con clangore/gcc e l'operatore di overload viene prelevato sia da espressioni binari (a+b) e le espressioni unari (+a), come mi aspetterei. Tuttavia gli operatori sono più limitati delle normali funzioni, nel senso che - per esempio - non è possibile sovraccaricare lo operator+() con tre argomenti.

L'utilizzo è legale e portatile?

EDIT Per dare un po 'di contesto, chiaramente non mi aspetto di poter definire operatori variadici o qualcosa del genere. La ragione per cui sono interessato a questo è per un brutto scherzo: mi piacerebbe fare alcuni operatori variadici in modo da poterli "sovrascrivere" con altre implementazioni non-variadiche. Poiché i modelli variadici sono considerati meno specializzati dei modelli non-variadici nelle regole di sovraccarico dei modelli di funzione, potrei ignorare un operatore variadico con uno non-variadico. Sì, è piuttosto orrendo :)

risposta

5

Prima di tutto, la definizione di fine, perché esistono specializzazioni valide con pacchetti non vuoti .

Ora, espressioni specifiche a+b o +a sono i.a. trasformato in chiamate non membri del modulo operator+(a, b) e operator+(a), rispettivamente ([over.match.oper]/2). La ricerca del nome trova quindi il modello di funzione dell'operatore, la cui specializzazione diventa parte dei candidati. Infine, [over.match.oper]/6 soli delegati sovraccaricare risoluzione come al solito:

L'insieme delle funzioni candidate per la risoluzione di sovraccarico è l'unione di candidati membri, i candidati non membri, e il built-in candidati. L'elenco degli argomenti contiene tutti gli operandi dell'operatore . La migliore funzione dall'insieme delle funzioni candidate è selezionata secondo 13.3.2 e 13.3.3.

Il codice funziona anche come previsto, dato che la risoluzione di sovraccarico e ordinamento parziale rispetterà il modello di funzione dell'operatore come tutti gli altri.


dichiarando quanto sopra per gli operatori unari, tranne forse postfix -- e ++, è malato-formato, senza bisogno di diagnostica. Cf. [temp.res]/(8.2).

+0

Grazie per la risposta, ho ho aggiunto un po 'di contesto alla domanda originale. – bluescarni

+0

@bluescarni Sì, va tutto bene. – Columbo

3

La norma limita il numero di argomenti (e la presenza di argomenti predefiniti) operatore funzione s, in [over.oper]:

8 - Una funzione operatore non può avere argomenti predefiniti ([dcl.fct. predefinito]), tranne dove esplicitamente indicato di seguito. Le funzioni dell'operatore non possono avere più o meno parametri del numero richiesto per l'operatore corrispondente, come descritto nel resto di questo sottopunto.

Tuttavia, quello che hai dichiarato è un modello di funzione operatore, che non ha tali restrizioni. Ciò significa che il tuo codice va bene; l'uso di unario o binario + verrà trasformato in una chiamata a operator+ con uno o due argomenti e verrà generata un'istanza appropriata del modello.

Sarebbe illegale se si dovesse specializzarsi o esplicitamente un'istanza del modello di funzione all'operatore un numero illegale di argomenti, dal momento che ([over.oper]):

1 - [... ] Una specializzazione di un modello di funzione dell'operatore è anche una funzione dell'operatore . [...]


Si noti che un effetto simile si ottiene se scriviamo un modello non variadic operatore funzione che può essere istanziato con i tipi non corretti:

template<class T> int operator+(T, T) { return 0; } // OK 
struct bar {}; template int operator+(bar, bar);  // OK 
template int operator+(int, int);     // Error is here 
Problemi correlati