C'è qualche modo per forzare compilatori C++ per eseguire la ricerca dei nomi per un data simbolo durante istanziazione di template (e non prima)?
Sì. Prima di tutto, il nome deve essere dipendente. Il nome f
in wrapper
quando utilizzato come f(t)
dipende dal fatto che t
dipende dal tipo. [Temp.dep]/1:
In un'espressione della forma:
postfix-espressione (
espressione-list opt)
dove il postfix-espressione è un qualificato-id, il qualificato-id denota un nome dipendente se
- qualsiasi espressioni nella espressione-list è un pacchetto di espansione (14.5.3),
- qualsiasi espressioni nella espressione-list è un tipo dipendente dalla espressione (14.6.2.2), o
- se il qualificato-id è un modello -id in cui nessuno degli argomenti modello dipende da un parametro di modello.
Il problema è che i nomi dichiarati dopo il modello stesso, vale a dire solo in l'istanza, ma non il contesto definizione, possono solo essere trovati utilizzando argomento nome dipendente ricerca. I suoi f
sovraccarichi solo prendere tipi fondamentali, ma quelli non hanno lo spazio dei nomi globale associato con loro in base al [basic.lookup.argdep]/2:
Se T
è un tipo fondamentale, i suoi gruppi associati di spazi dei nomi e Le classi sono entrambe vuote.
Così i f
s stati dichiarati non possono mai essere trovato se gli argomenti sono dello stesso tipo dei parametri. Un piccolo trucco può aiutare:
template <typename T>
struct refwrap
{
T&& t;
refwrap(T&& t) : t(std::forward<T>(t)) {}
operator T&&() {return std::forward<T>(t);}
};
template <typename T>
auto make_refwrap(T&& t) -> refwrap<T> // making use of reference collapsing
{ return {std::forward<T>(t)}; } // inside refwrap to get forwarding
Questo modello, quando ha dichiarato nel namespace globale, causerà ADL a considerarlo. Riscrivere wrapper
come segue:
template <class T>
auto wrapper(T t) -> decltype(f(make_refwrap(t)))
{
return f(make_refwrap(t));
}
Demo. Questo non è il modo corretto di farlo, poiché fallirà in scenari più complessi.
Perché non si utilizza la specializzazione del modello? – Chiel
@ Chiel: Grazie, ottima idea! Quindi sostituirò 'f' con un modello di classe? Funziona, ma avevo sperato in una soluzione che non mi richiedesse di cambiare la definizione di 'f' (molto). O hai qualcos'altro in mente? –
È possibile utilizzare un valore predefinito che si applica alla maggior parte dei casi e alla specializzazione laddove richiesto, vedere la mia risposta. – Chiel