2015-01-09 16 views
8

Come posso ottenere l'arità di un tipo di funzione arbitrario utilizzato come parametro di modello?Ottieni la funzione dal parametro modello

La funzione può essere una funzione normale, una lambda o un funtore. Esempio:

template<typename TFunc> 
std::size_t getArity() 
{ 
    // ...? 
} 

template<typename TFunc> 
void printArity(TFunc mFunc) 
{ 
    std::cout << "arity: " << getArity<TFunc>() << std::endl; 
} 

void testFunc(int) { } 

int main() 
{ 
    printArity([](){}); // prints 0 
    printArity([&](int x, float y){}); // prints 2 
    printArity(testFunc); // prints 1 
} 

Ho accesso a tutte le funzionalità di C++ 14.

Devo creare la specializzazione per ogni tipo di funzione (e tutti i rispettivi qualificatori)? O c'è un modo più semplice?

+2

Qual è la tua definizione di origine di un lambda generico variadico? O di un funtore con 'operatore()' s sovraccaricato che prende un numero diverso di parametri? –

+0

possibile duplicato di [È possibile capire il tipo di parametro e il tipo di ritorno di un lambda?] (Http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter -type-and-return-type-of-a-lambda) – Barry

+1

Hai solo bisogno di due overload: uno per i puntatori di funzione (facile, basta usare 'sizeof ... 'sul pacchetto argomento dedotto) e uno per lambdas e altre classi (prendi 'decltype' del suo' operator() 'e poi fai la stessa cosa). Se 'operator()' è sovraccarico, sei sfortunato. – Brian

risposta

7

Supponendo che tutti i operator() 's e le funzioni di cui stiamo parlando non sono modelli o sovraccarico:

template <typename T> 
struct get_arity : get_arity<decltype(&T::operator())> {}; 
template <typename R, typename... Args> 
struct get_arity<R(*)(Args...)> : std::integral_constant<unsigned, sizeof...(Args)> {}; 
// Possibly add specialization for variadic functions 
// Member functions: 
template <typename R, typename C, typename... Args> 
struct get_arity<R(C::*)(Args...)> : 
    std::integral_constant<unsigned, sizeof...(Args)> {}; 
template <typename R, typename C, typename... Args> 
struct get_arity<R(C::*)(Args...) const> : 
    std::integral_constant<unsigned, sizeof...(Args)> {}; 

// Add all combinations of variadic/non-variadic, cv-qualifiers and ref-qualifiers 

Demo.

+1

Esiste una versione come la tua che supporti anche lambdas generici? Http://coliru.stacked-crooked.com/a/1192b2686726d41d – James

Problemi correlati