2009-08-15 19 views
6

Say voglio una funzione ++ C per eseguire operazioni aritmetiche su due ingressi, trattandoli come un dato tipo:Passa il puntatore al template come funzione?

pseudo:

function(var X,var Y,function OP) 
{ 
if(something) 
    return OP<int>(X,Y); 
else if(something else) 
    return OP<double>(X,Y); 
else 
    return OP<string>(X,Y); 
} 

funzioni che si adattano OP potrebbero essere come:

template <class T> add(var X,var Y) 
{ 
return (T)X + (T)Y; //X, Y are of a type with overloaded operators 
} 

Quindi, la domanda è: quale sarebbe la firma per la funzione? Se le funzioni dell'operatore non sono basate su modelli, posso farlo, ma mi confondo con questa complessità extra.

+1

Vedere gli argomenti del modello di modello. (E non è un errore di battitura.) – sbi

+0

+1, questa è fondamentalmente la risposta corretta su come passare OP. – MSalters

+0

Ho aggiunto questo come risposta. Spero di non aver inserito errori stupidi. – sbi

risposta

4

Stai cercando questo?

template<class T> T add(T X, T Y) 
{ 
    return X + Y; 
} 

O stai cercando qualcosa che chiama qualcosa come aggiungi?

template<class T, class F> 
T Apply(T x, T y, F f) 
{ 
    return f(x, y); 
} 

chiamata Via:

int x = Apply(2, 4, add<int>); 
+0

Credo che voglia passare * add * ** senza ** specificando * int * come argomento del template. – izogfif

5

Sono un po 'confuso ... perché il tipo di differenziazione nel pseudo-codice?

modelli C++ consentono tipo detrazione sui modelli:

template <typename T, typename F> 
T function(T x, T y, F op) { 
    return op(x, y); 
} 

Qui, F si inserisce nulla (soprattutto funzioni) che può essere chiamata con la sintassi chiamata () funzione e accettando esattamente due argomenti di tipo T (o implicitamente convertibile ad esso).

+0

Penso che questo è quello che intendevo, non pensavo a una funzione come argomento modello. –

+0

L'unico problema è che F non può essere una funzione modello con argomenti modello sconosciuti, deve essere una funzione non modello o una funzione modello con tutti i tipi di modello specificati. – izogfif

+0

@izogfif È inoltre possibile specificare esplicitamente gli argomenti del modello. Deducandoli può essere fatto usando la metaprogrammazione del modello. Ma in ogni caso sembra che questo abbia risposto alla domanda dell'OP, non c'è bisogno di complicarlo ulteriormente. –

0

Non sono sicuro di cosa significhi questa cosa var nella tua domanda. Non è certamente una parola chiave C++ valida, quindi presumo sia un tipo simile a boost:any. Inoltre, la funzione non ha un tipo di risultato. Ho aggiunto un altro var, qualunque cosa potrebbe essere. La vostra soluzione potrebbe essere la seguente:

template< template<typename> class Func > 
var function(var X, var Y, Func OP) 
{ 
if(something) 
    return OP<int>(X,Y); 
else if(something else) 
    return OP<double>(X,Y); 
else 
    return OP<string>(X,Y); 
} 

L'argomento divertente modello è un modello di per sé, da cui il nome "template argomento". Passi nel nome di un modello, non in un'istanza. Cioè, si passa std::plus, non std::plus<int>:

return function(a, b, std::plus); 
+0

Non funziona in Visual C++ 2008, Visual C++ 2010 a causa di un errore di compilazione. – izogfif

+0

@izogfif: Ora imaging, per un momento, hai fornito l'errore esatto del compilatore. Qualcuno potrebbe essere arrivato, l'ha guardato, ha capito qual è il problema e ha pubblicato una soluzione. Certo, non lo vogliamo, quindi è bene che non l'abbia previsto. – sbi

+0

Buon punto. Ecco il codice che ho cercato di compilare e gli errori sollevati dal compilatore (alla fine del codice): http://pastebin.com/YyhX9ruT – izogfif

5

funzioni dei modelli non possono essere passati come argomenti di template. È necessario dedurre manualmente gli argomenti del modello per questa funzione prima di passarla a un'altra funzione del modello.Ad esempio, la funzionalità dei

T sum(T a, T b) 
{ 
    return a + b; 
} 

Si vuole passarlo a callfunc:

template<typename F, typename T> 
T callFunc(T a, T b, F f) 
{ 
    return f(a, b); 
} 

Non si può semplicemente scrivere

int a = callFunc(1, 2, sum); 

Devi scrivere

int a = callFunc(1, 2, sum<int>); 

Per essere in grado di passare sum senza scrivere int, devi scrivere un functor - struct o class con operator() che chiamerà la tua funzione template. Quindi puoi passare questo functor come argomento del template. Ecco un esempio.

template<class T> 
T sum(T a, T b) 
{ 
    return a + b; 
} 
template<class T> 
struct Summator 
{ 
    T operator()(T a, T b) 
    { 
     return sum<T>(a, b); 
    } 
}; 
template<template<typename> class TFunctor, class T> 
T doSomething(T a, T b) 
{ 
    return TFunctor<T>()(a, b); 
    //Equivalent to this: 
    //TFunctor<T> functor; 
    //return functor(a, b); 
} 


int main() 
{ 
    int n1 = 1; 
    int n2 = 2; 
    int n3 = doSomething<Summator>(n1, n2); //n3 == 3 
    return 0; 
} 
+0

Questa confusione non si presenterebbe in primo luogo se le persone usassero la terminologia corretta: " funzioni modello "non esistono, sono" modelli di funzioni ". Cioè, nel tuo esempio 'callFunc (1, 2, sum);' sei ** non ** passando una funzione a 'callFunc', stai passando un * template * ad esso (e come il tuo esempio ti mostra * può * passare template come argomenti del template, ma solo template * class *, non * function * templates). –

+0

Hm .. Non ci ho pensato in questo modo. Credo che la domanda originale dovrebbe essere "Come passare il modello di funzione come argomento modello di funzione", quindi, giusto? – izogfif

+0

Quindi, come faresti funzionare questa soluzione se sum è un membro non statico di una classe? –

1

Io uso lambda per questo.

auto add = [](const auto& lhs, const auto& rhs) { 
    static_assert(std::is_arithmetic<typename std::decay<decltype(lhs)>::type>::value, 
      "Needs to be arithmetic."); 
    static_assert(std::is_arithmetic<typename std::decay<decltype(rhs)>::type>::value, 
      "Needs to be arithmetic."); 
    return lhs + rhs; 
}; 

template<typename LHS, typename RHS, typename FUNC 
    , typename OUT = typename std::result_of<FUNC(LHS, RHS)>::type> 
constexpr OUT do_arithmetic(LHS lhs, RHS rhs, FUNC func) { 
    return func(lhs, rhs); 
} 

constexpr auto t = do_arithmetic(40, 2, add); 
static_assert(t == 42, "Wrong answer!"); 
static_assert(std::is_same<std::decay<decltype(t)>::type, int>::value, 
     "Should be int."); 
Problemi correlati