Domanda

Considera il seguente codice:

#include <stdio.h>

namespace Foo {
  template <typename T>
  void foo(T *, int) { puts("T"); }

  template <typename T>
  struct foo_fun {
    static void fun() { foo((T *)0, 0); };
  };
}

namespace Foo {
  void foo(int *, int) { puts("int"); }
}

using namespace Foo;

int main() {
  foo_fun<int> fun;
  fun.fun();
}

Qual è l'output previsto? & Quot; T " o int?

Un compilatore (gcc 4.0.1 dell'Xcode 3.1.2 di Apple) ha prodotto "int", altri due compilatori (gcc 4.1.2 e 4.1.3) ha prodotto "T".

Se sposto la dichiarazione / definizione foo (int *, int) prima della versione foo (T *, int), tutto l'output "int". L'ordine di sovraccarico / specializzazione in questo caso è definito dalla norma attuale?

È stato utile?

Soluzione

Il secondo void foo (... è un sovraccarico (e non una specializzazione) che non è visibile nella definizione di foo_fun :: fun , quindi ha vinto ' si trova nel contesto della definizione del modello. Poiché T * è un tipo dipendente, la risoluzione di foo nell'espressione foo ((T *) 0, 0) verrà ritardato fino al tempo di istanza del modello e verrà considerato anche il contesto dell'istanza. Tuttavia, il 14.6.4.2 della norma afferma che se il nome della funzione è un ID non qualificato ma non un template-id quindi per la ricerca non ADL vengono considerate solo le funzioni visibili nel punto di definizione del modello. Non ci sono argomenti di funzione dallo spazio dei nomi Foo quindi non si verifica alcuna ricerca dipendente dall'argomento, quindi viene chiamata la versione del modello di pippo e non il sovraccarico non di modello.

Mille grazie a litb per le correzioni a questa risposta.

Se l'hai trasformata in una specializzazione come di seguito, quindi quando le specializzazioni vengono scelte al momento dell'istanza del modello, la specializzazione può essere chiamata fino a quando la specializzazione pertinente è visibile nel punto in cui il modello della funzione viene istanziato per la prima volta per int .

namespace Foo {
    template<>
    void foo<int>(int *, int) { puts("int"); }
}

Capitolo 14 dello standard attuale, ma non è molto leggibile :)

Modifica: se dovessi scegliere la parte più rilevante dello standard sarebbe probabilmente 14.6 [temp.res] para 9. (Leggermente abbreviato) Se un nome non dipende da un template-parametro , una dichiarazione per tale nome deve essere portata nel punto in cui il nome appare nella definizione del modello; il nome è legato alla dichiarazione trovata in quel punto e questa associazione non è influenzata dalle dichiarazioni che sono visibili nel punto di istanza.

Modifica, modifica: ma devi anche tener conto del 14.6.4.2 [temp.dep.candidate]. È molto difficile e pericoloso cercare di fare riferimento allo standard a causa di tutte le interdipendenze, questa risposta è un esempio emblematico.

Altri suggerimenti

Come regola generale, di due versioni di un compilatore, è più probabile che la successiva sia più standard.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top