2011-11-28 6 views
5

Supponiamo che se ho questo,Regole per determinare l'insieme del tipo di funzione compatibile con std :: function <R(T1,T2)>?

std::function<int(int,int)> fs; 

allora come è possibile determinare l'insieme di funzioni (o oggetti funzionali) che fs possono essere inizializzate con?

Quale delle folllowing è consentito e non che:

std::function<int(int,int)> fs = [](int, int) { return int(10); }; 
std::function<int(int,int)> fs = [](char, char) { return char(10); }; 
std::function<int(int,int)> fs = [](int, short) { return int(10); }; 
std::function<int(int,int)> fs = [](double, int) { return float(10); }; 
std::function<int(int,int)> fs = [](int, wchar_t) { return wchar_t(10); }; 

std::function<int(int,int)> fs = [](const char*, int){ return "string"; }; 
std::function<int(int,int)> fs = [](const char*, int){ return 10; }; 
std::function<int(int,int)> fs = [](const char*, int){ return std::string(); }; 

Naturalmente, posso compilare e vedere uno che compila bene, e che non lo fa. Ma questo non mi aiuta a capire le variazioni nei tipi di parametri e il tipo di ritorno. Fino a che punto posso andare ad usare tipi diversi per loro?

Per dirlo in altre parole, se ho dato una funzione (o oggetto funzione), come posso determinare in fase di compilazione se è compatibile con std::function<int(int,int)> o no? Ho poca comprensione, ma non sono abbastanza sicuro.

Quindi, per favore aiutami a capire e stabilire le regole per determinare l'insieme del tipo di funzione compatibile con std::function<R(T1,T2)>? Metaprogramming può aiutarmi qui a notificare agli utenti, generando messaggi di errore piacevoli, se usano una funzione incompatibile?

proposito, il primo gruppo sembra essere compatibile: http://ideone.com/hJpG3

risposta

4

L'oggetto (puntatore a funzione o functor) devono essere richiamabile con un determinato tipo di argomento, cioè fun(declval<Types>() ...) è ben formato e conversione implicita R.

Vedere C++ 11 §20.8.2 in particolare; fornisce vari casi speciali per i puntatori ai membri, ecc. §20.8.11.2/2 e 20.8.11.2.1/7 legano questo al costruttore std::function.

4

Non esiste una soluzione di metaprogrammazione preconfezionata. Ho programmato i seguenti tratti per aiutare con questa domanda. Questi tratti implementano semplicemente le sezioni indicate nella risposta di Potatoswatter. I commenti del codice elencano anche i punti elenco nelle sezioni di riferimento.

template <class _F, class ..._Args> struct __invokable; 
template <class _F, class ..._Args> struct __invoke_of; 

http://llvm.org/svn/llvm-project/libcxx/trunk/include/type_traits

ho usato questi per creare un privato "trait membro" della std::function:

template <class _F, bool = __invokable<_F&, _ArgTypes...>::value> 
    struct __callable; 

http://llvm.org/svn/llvm-project/libcxx/trunk/include/functional

E 'venuto in mente che questi potrebbero fare un buon materiale tr2 (contiene i caratteri di sottolineatura iniziali). Se sei d'accordo, forse dovresti informare il rappresentante del tuo Corpo Nazionale.

Se si desidera utilizzare questi tratti, il codice è open source. Ma lo apprezzerei se rispettassi la licenza open source includendo le informazioni sul copyright in ogni file.

+0

Sembra che questa risposta sia nel contesto della funzionalità esposta dalla Libreria standard ... se la mia risposta non è corretta, potresti commentare perché? Modifica: questa caratteristica sembra ignorare la conversione del valore di ritorno ... – Potatoswatter

+0

@Potatoswatter: ho appena esaminato l'implementazione di questi tratti. Esse dipendono da 'std :: forward',' std :: is_convertible' e 'std :: is_same'. Potrebbero essere implementati come parte di uno std :: lib o no.Ho anche esaminato la mia risposta e non vedo dove ho lasciato intendere che la tua risposta sia errata. La mia risposta fornisce semplicemente un'implementazione metaprogrammante delle sezioni a cui fai riferimento. L'OP ha chiesto una soluzione per metaprogrammazione, quindi ho pensato che la mia risposta fosse pertinente. Sulla conversione del valore di ritorno: questo è trattato in '__callable' usando' __invoke_of' e 'is_convertible'. –

+1

Ok. L'unico disaccordo sarebbe che considero la mia risposta come la "risposta standard preconfezionata". Per quanto riguarda la conversione del tipo di reso, non ho seguito il collegamento e ho pensato che fosse un modello non membro, senza accesso al tipo di reso desiderato. A livello di utente, non è 'std :: is_convertible :: type, R> :: value' sufficient? Suppongo che dipenda se vuoi SFINAE o un risultato 'falso'. – Potatoswatter

Problemi correlati