2009-06-02 2 views
13

considerare questo codice semplice e senza senso.C++ modelli di funzioni e funzioni

#include <iostream> 

struct A { 
    template<int N> 
    void test() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a.test<1>(); 
} 

È un esempio molto semplice di un modello di funzione. Che cosa succede se, tuttavia, volevo sostituire A::test con un sovraccarico operator() per renderlo un funtore?

#include <iostream> 

struct A { 
    template<int N> 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a<1>(); // <-- error, how do I do this? 
} 

Certamente se la presero operator() parametri che erano a carico del modello, il compilatore potrebbe dedurre il modello. Ma non riesco a capire la sintassi corretta per specificare i parametri del modello con un functor senza parametri.

Esiste un modo corretto per farlo?

Ovviamente, questo codice dovrebbe funzionare dal momento che bypassa la sintassi funtore:

a.operator()<1>(); 

ma che sconfigge un pò lo scopo di esso che è un :-P funtore.

+0

+1: Sintassi strana per l'utilizzo in offuscamento del codice. Dovrebbe essere menzionato in http://thc.org/root/phun/unmaintain.html :-) –

risposta

9

Non c'è un altro modo "diretto" So diverso dal:

a.operator()<1>(); 

sintassi. Se sei aperto alla modifica del codice, lo spostamento del parametro del modello nella classe potrebbe funzionare oppure utilizzare un (boost | tr1) :: bind per creare un oggetto funzione (boost | tr1) ::.

24

È possibile chiamare solo

a.operator()<1>(); 

, ma che non sarebbe utilizzando un funtore. I Functional hanno bisogno di un operatore non template(), in quanto devono essere chiamati come varname() e questo non funzionerà con il tuo codice.

per renderlo un vero e proprio funtore modificare il codice di una classe template (funtori sono classi):

#include <iostream> 

template<int N> 
struct A { 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A<1> a; 
    a(); 
} 
2

Si sta tentando di passare un parametro modello a un'istanza di un oggetto, che per quanto ne so non è permesso. È possibile passare solo i parametri dei modelli alle funzioni del modello o agli oggetti del modello.

a.test < 1>(); e a.operator() < 1>(); funzionano perché funzionano come funzioni modello.

Usa boost :: bind (controlla le librerie di boost) per risolvere il problema.

struct A { 
    void operator()(int n) { 
     std::cout << n << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) { 
    A a; 
    boost::function<void()> f = boost::bind<void>(a, 1); 
    f(); // prints 1 

    return 0; 
} 

E non è nemmeno necessario fare confusione con i modelli!

0

No, non c'è modo di aggirarlo. Come hai detto tu, devi chiamare l'operatore esplicitamente (che vanifica lo scopo), oppure gli argomenti del template devono essere in grado di essere dedotti dal compilatore.

1

Sei bloccato. Hai preso in considerazione qualcosa come

struct A { 
    template<int N> 
    struct B 
    { 
     void operator()() 
     { std::cout << N << std::endl; } 
    }; 

    template<int N> 
    B<N> functor() {return B<N>();} 
}; 

int main() 
{ 
    A a; 
    a.functor<1>()(); 
}