2013-07-19 15 views
6

C++ consente ai parametri del modello non di tipo di essere puntatore, inclusi il puntatore di funzione, il tipo. Recentemente ho chiesto a question informazioni su ciò per cui è utile, e questo è il seguito di one of the answers.C'è un modo per dedurre il valore di un parametro del modello di puntatore a funzione?

È possibile dedurre il valore di un parametro del modello di puntatore a funzione, da un argomento di funzione che è il puntatore di funzione in questione? Ad esempio:

using VoidFunction = void(*)(); 

template <VoidFunction F> 
void templ(VoidFunction); 

... 

void func(); // a VoidFunction 

... 

templ<func>(func); // works, but I have to specify the template parameter explicitly 
templ(func);  // <-- I would like to be able to do this 

C'è un modo per ottenere questa deduzione? Sembra tecnicamente possibile dal punto di vista di un implementatore del compilatore, purché l'argomento della funzione possa essere risolto con una funzione nel codice in fase di compilazione.

Se vi state chiedendo le motivazioni alla base di questo, vedere i commenti sotto this answer, in particolare una possibile ottimizzazione per l'implementazione di std::bind().

EDIT: Mi rendo conto che ho potuto semplicemente rimuovere l'argomento della funzione e utilizzare l'argomento modello, come in templ<func>(). Il mio unico scopo di aggiungere l'argomento della funzione era di cercare di evitare di dover passare l'argomento del template.

Credo che quello che voglio veramente, è di dedurre anche la tipo del puntatore a funzione, come in:

template <typename Function, Function F> 
void templ(/* something */); 

e quindi essere in grado di chiamare

templ(func); 

o

templ<func>(); 

e avere sia il tipo che il valore da dedurre da un singl e menzione del puntatore della funzione.

Speranza che ha più senso ora.

+0

Come poteva dedurlo? Per esempio, potrei fare questo: 'template void foo (std :: size_t i) {int arr [N];/* fill */return arr [i];} '. Vorrei assolutamente un errore se mi capitasse di dimenticare l'argomento del modello quando questa deduzione poteva essere fatta. – chris

+0

Vieni a pensarci, non sono sicuro di capire perché debba essere passato anche come argomento di funzione. 'Templ ();' sufficiente? – chris

+0

@chris: Giusto, la mia domanda non ha molto senso come scritto :) Vedi la mia modifica. – HighCommander4

risposta

2

Gli argomenti del modello per una funzione vengono dedotti dai tipi dei parametri del modello della funzione. Gli argomenti del modello possono essere dedotti da un tipo solo quando quel tipo è uno dei moduli consentiti. Le forme consentite sono specificate in [temp.deduct.type]

argomenti modelli possono essere dedotte in molti contesti diversi, ma in ogni caso è confrontato un tipo specificato in termini di parametri di modello (lo chiamano P) con un tipo effettivo (chiamatelo A) e viene effettuato un tentativo di trovare valori argomento modello (un tipo per un parametro di tipo, un valore per un parametro non di tipo o un modello per un parametro di modello) che renderà P, dopo la sostituzione dei valori dedotti (chiamarlo dedotto A), compatibile con A.

Un tipo di modello argomento T, un argomento template TT o un modello non-tipo di argomento i può dedurre se P e A avere una delle seguenti forme:

T 
cv-list T 
T* 
T& 
T[integer-constant] 
template-name (where template-name refers to a class template) 
type(*)(T) 
T(*)() 
T(*)(T) 
T type::* 
type T::* 
T T::* 
T (type::*)() 
type (T::*)() 
type (type::*)(T) 
type (T::*)(T) 
T (type::*)(T) 
T (T::*)() 
T (T::*)(T) 
type[i] 
template-name&lti> (where template-name refers to a class template) 
TT<T> 
TT<i> 
TT<>

dove (T) rappresenta gli elenchi di argomenti in cui almeno un tipo di argomento contiene uno T e () rappresenta gli elenchi di argomenti in cui nessun parametro contiene uno T. Allo stesso modo, <T> rappresenta elenchi di argomenti di template in cui almeno un argomento contiene un T, <i> rappresenta elenchi di argomenti di template in cui almeno un argomento contiene un i e <> rappresenta liste di argomenti di template in cui nessun argomento contiene un T o un i.

Quando si considera solo non di tipo argomenti del template, i relativi moduli sono quelli che contengono i:

type[i] 
template-name&lti> (where template-name refers to a class template) 
TT<i>

Pertanto non è possibile dedurre il valore direttamente dal valore di argomento di funzione che è il puntatore della funzione. Tuttavia è possibile dedurre il valore di un argomento modello non di tipo se il parametro funzione ha uno dei moduli specificati.

Il codice seguente lo mantiene racchiudendo il valore dell'argomento modello non di tipo in un modello di classe denominato NonType. Il parametro f ha il formato template-name<i>, rendendo possibile dedurre il valore del relativo argomento modello non di tipo.

template<typename T, T value> 
struct NonType {}; 

template<typename T, T value> 
void f(NonType<T, value>) 
{ 
} 

void g(); 

struct A 
{ 
    void f(); 
    int m; 
}; 

int i; 

#define MAKE_NONTYPE(value) NonType<decltype(value), (value)>() 

int main() 
{ 
    f(MAKE_NONTYPE(0)); // NonType<int, 0> 
    f(MAKE_NONTYPE(&g)); // NonType<void(*)(), &g> 
    f(MAKE_NONTYPE(&A::f)); // NonType<void(A::*)(), &A::f> 
    f(MAKE_NONTYPE(&A::m)); // NonType<int A::*, &A::m> 
    f(MAKE_NONTYPE(&i)); // NonType<int*, &i> 
} 

noti che decltype e la macro MAKE_NON_TYPE sono usati qui solamente come vantaggio, per evitare di dover scrivere il pieno modello di lista degli argomenti di NonType

Problemi correlati