2009-11-19 12 views
7

qualcuno ha già fatto questa domanda, ma il thread ha finito con la domanda originale che non ha avuto risposta.templated operator() overload C++

si supponga di avere questo:

template<size_t i, class f_type> 
void call_with_i(f_type f); 

functor_type quando è:

a) una struttura con un metodo che ha la seguente firma:

template<size_t i> operator()() const; 

o, b) una funzione simile a questa:

template<size_t i> foo(); 

che voglio "call_with_i < 42> (foo)" equivalente a "foo < 42>()", ma io non riesco a capire la sintassi giusta per realizzare questo obiettivo. Sarei soddisfatto con una soluzione che faccia solo (a) ma (a) + (b) sarebbe ottima . Ho già provato queste sintassi:

f<i>(); // doesn't work 
f()<i>; // doesn't work 
f.operator<i>(); // doesn't work 
f.operator()<i>; // doesn't work 
f.operator()<i>(); // works on msvc, but doesn't work on gcc. 

Come si richiama operatore() con argomenti espliciti template? C'è un modo per invocarlo in modo che la stessa sintassi possa anche chiamare una funzione libera basata su modelli?

p.s. Se ti stai chiedendo per cosa sto usando questo, è perché sto scrivendo una funzione repeat_to dove repeat_to < 10> (f) richiama f (0) poi f (1) ... f (10). Lo sto usando per scorrere più vettori boost :: fusion in parallelo per indice. si, potrei usare gli iteratori, o potrei semplicemente usare una funzione membro chiamata, ma voglio ancora sapere la risposta.

modifica nota: ho eliminato la roba perché passare una funzione basata su modello come argomento non ha alcun senso.

+0

Non è stata data risposta perché non è possibile. – GManNickG

risposta

13

Il modello membro è un nome dipendente, poiché la sua semantica dipende dal tipo di f_type. Ciò significa che si dovrebbe mettere "modello" prima che il suo nome (per disambiguare l'uso del "meno-che" token), simile a come si dovrebbe mettere typename prima di nomi qualificati dipendenti:

template<size_t i, class f_type> 
void call_with_i(f_type f) { 
    f.template operator()<i>(); 
    // f.template foo<i>(); 
} 

Per risolvere il problema, è può utilizzare un tipo di supporto:

template<size_t N> struct size_t_ { }; // or boost::mpl::int_ 

template<size_t i, class f_type> 
void call_with_i(f_type f) { 
    f(size_t_<i>()); 
} 

Ora, si potrebbe definire il operator() come segue:

template<size_t i> void operator()(size_t_<i>) const { 
    // i was deduced automatically by the function argument. 
} 

Questo è particolarmente utile per i costruttori su modelli, per w che non puoi fare f_type()<i>() o qualcosa del genere. Saranno avere in questo caso deducibile.

+0

@Johannes: perché non specializzarsi per le funzioni che utilizzano SFINAE? –

+0

funziona alla grande! assolutamente fantastico. sei il mio meta-eroe. ah, e la tua idea di usare mpl :: int_ è troppo intelligente. – Glenn

+0

@ laulaulabs.mp, felice di essere di aiuto :) –

0
#include <iostream> 

template<size_t i, class f_type> void call_with_i(f_type f); 

struct A { 

    template < size_t i > 
    void operator()() const { 
     /* no link err in demo */ 
    } 

    template < size_t i > 
    void foo() { 
     /* no link err in demo */ 
    } 
}; 

int main(int argc, char * const argv[]) { 
    A f; 

    enum { Constant = 42 }; 

    f.operator()<Constant>(); 
    f.foo<Constant>(); 

    return 0; 
} 

Esiste un modo per richiamare in modo che la stessa sintassi sarebbe anche chiamare una funzione libera su modelli?

Potete chiarire? (pseudocodice, o qualcosa di simile)

+0

in realtà la mia parte sulla funzione libera basata su modelli è semplicemente assurda dato che non è possibile passare un modello di funzione come argomento. – Glenn

1

In un caso come il vostro, userei boost :: function come tipo di functor. È quindi possibile passare sia gli oggetti funzione che i puntatori funzione mantenendo la stessa interfaccia.