2017-12-17 6 views
2

Betrachten Sie den folgenden Code nehmen mit:Detect die maximale Anzahl von Argumenten eine Funktion kann Metaprogrammierung

template <class T, class F> 
std::size_t maximum_number_of_arguments(F&& f) { 
    // Code here 
} 

ich eine Funktion möchte, die die maximale Anzahl von Argumenten des Typs finden T, dass die abrufbaren f nehmen .

Zum Beispiel für folgende Überlastung Satz:

void f(int, int); // f called with 2 ints compiles 
void f(int, int, int); // f called with 3 ints compiles 
void f(int, char, int, double); // f called with 4 ints compiles 
void f(int, std::string, int, int, int); // f called with 5 ints does not compile 

Als Ergebnis:

maximum_number_of_arguments<int>(f) 

sollte 4 zurückzukehren.

Ich denke, der Weg, um eine begrenzte Anzahl von Parametern zu beheben, die eine Funktion (zum Beispiel 256) nehmen kann, und testen Sie alle Möglichkeiten, und verfolgen Sie die Aufrufe, die nicht kompilieren fehlschlägt. Wie macht man das mit Template/Contexpr Metaprogrammierung?

EDIT: Um die Kommentare auf der Tatsache zu beantworten, dass wir nicht eine Überlastung Satz an eine Funktion kann (mein Beispiel mit f ist wahrscheinlich nicht die beste):

#include <iostream> 

struct functor 
{ 
    void operator()(int) {std::cout << "int" << std::endl;} 
    void operator()(int, int) {std::cout << "int, int" << std::endl;} 
    void operator()(int, int, int) {std::cout << "int, int, int" << std::endl;} 
}; 

template <class F> 
void caller(F&& f) 
{ 
    std::forward<F>(f)(1); 
    std::forward<F>(f)(1, 2); 
    std::forward<F>(f)(1, 2, 3); 
} 

int main(int argc, char* argv[]) 
{ 
    functor f; 
    caller(f); 
    return 0; 
} 
+7

Wie lautet die Antwort für 'printf'? –

+3

Oder 'Vorlage void foo (T ...)' – Barry

+3

"Ich möchte eine Funktion, die die maximale Anzahl von Argumenten des Typs finden kann ...." - warum? Was ist der Anwendungsfall? Nicht lustig, aber das riecht wie ein x-y-Problem. –

Antwort

3

Was Sie fragen, ist nicht gerade trivial ...

Wenn Sie in der maximalen Anzahl von ganzzahligen interessiert, dass allein verwendet werden kann, eine Funktion oder eine Reihe von Funktion mit einer gemeinsamen Kennung zu nennen, die Anrufe mit anderen Typen ohne ...

ich meine ... wenn die Prüfung für den folgenden Satz von f() Funktionen

void f(int, int); 
void f(int, char, int); 
void f(int, std::string, int, int, int); // excluded by std::string 

sollte 3 bekommen, weil die Version, die eine Empfang std::string ausgeschlossen werden soll ...

Nun ... mit einem Makro (so meine Lösung ist intrinsisches Übel), die einen Scheck Struktur definieren, um ein Symbol gewidmet

setMaxStruct(f); 

Sie können die maximale Anzahl von integer-Argumenten erhalten (mit einem einstellbaren aber vorbelegt maximal) etwas zu schreiben, wie folgt

std::cout << "--- f: " << getMaxArgsFor_f<int>::value << std::endl; 

Hier finden Sie eine vollständige Beispiel Arbeits

#include <utility> 
#include <iostream> 
#include <type_traits> 

template <typename T, std::size_t> 
using typer = T; 

#define setMaxStruct(func)          \ 
                    \ 
template <typename Type, std::size_t MaxArgs = 64U>    \ 
struct getMaxArgsFor_ ## func          \ 
{                \ 
    template <typename, std::size_t ...>       \ 
    static std::false_type isCallable (...);      \ 
                    \ 
    template <typename T, std::size_t ... Is>      \ 
    static auto isCallable (int)         \ 
     -> decltype(func(std::declval<typer<T, Is>>()...),   \ 
        std::true_type{});       \ 
                    \ 
    template <typename T, std::size_t ... Is>      \ 
    static constexpr bool getMaxTH3        \ 
     (std::index_sequence<Is...> const &)      \ 
    { return decltype(isCallable<T, Is...>(0))::value; }   \ 
                    \ 
    template <typename T, std::size_t I>       \ 
    static constexpr bool getMaxTH2()        \ 
    { return getMaxTH3<T>(std::make_index_sequence<I>{}); }  \ 
                    \ 
    template <typename T, std::size_t ... Is>      \ 
    static constexpr std::size_t getMaxTH1       \ 
     (std::index_sequence<Is...> const &)      \ 
    {                \ 
     std::size_t ret (-1);          \ 
                    \ 
     ((ret = getMaxTH2<T, Is>() ? Is : ret), ...);    \ 
                    \ 
     return ret;             \ 
    }                \ 
                    \ 
    template <typename T, std::size_t MaxAs>      \ 
    static constexpr std::size_t getMaxT()      \ 
    { return getMaxTH1<T>(std::make_index_sequence<MaxAs>{}); } \ 
                    \ 
    static constexpr std::size_t value = getMaxT<Type, MaxArgs>(); \ 
} 

void f(int, int); 
void f(int, int, int); 
void f(int, char, int, double); 
void f(int, std::string, int, int, int); 

template <typename ... Args> 
void h (Args ... args); 

setMaxStruct(f); 
setMaxStruct(g); 
setMaxStruct(h); 

int main() 
{ 
    std::cout << "--- f: " << getMaxArgsFor_f<int>::value << std::endl; 
    std::cout << "--- g: " << getMaxArgsFor_g<int>::value << std::endl; 
    std::cout << "--- h: " << getMaxArgsFor_h<int>::value << std::endl; 
} 

dass Beobachten von f Sie 4 erhalten, von g Sie erhalten size_t(-1) (g() nicht definiert ist) und von h() Sie 63 (den Maximalwert erhalten minus 1).

Verwandte Themen