2017-12-17 14 views
2

を使用して取ることができます検出します。次のオーバーロード・セットについては、例えばを考えてみましょう次のコードを引数の最大数の関数は、テンプレートメタプログラミング

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 

結果:

maximum_number_of_arguments<int>(f) 

4を返すべきです。

関数がとりうるパラメータの数を制限して(たとえば256)、すべての可能性をテストし、コンパイルに失敗しない呼び出しを追跡する方法を推測します。どのようにテンプレート/ contexprメタプログラミングでこれを行うには?

EDIT:私たちは機能に設定過負荷を渡すことができないという事実上のコメントに答えるために(fと私の例では、おそらく最高ではありません):あなたが聞いて何

#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

'printf'の答えはどうでしょうか? –

+3

または 'template void foo(T ...)' – Barry

+3

"タイプの引数の最大数を見つけることができる関数が必要です。" - なぜですか?ユースケースは何ですか?面白くないですが、これはx-y問題のようなにおいがします。 –

答えて

3

は正確に簡単ではありません...

だけでは、他のタイプの呼び出しを除く、共通の識別子で機能や関数の集合を呼び出すために使用することができることを、整数の最大数に興味があれば...

私が意味する... std::stringを受けるバージョンは除外すべきであるため、f()機能

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

次の一連のチェックが...と

うーん...を3を取得する必要がある場合マクロ(ので、私の解決策は、本質的な悪である)あなたが(設定可能しかし、債務不履行最大で)整数の引数の最大数を取得することができ、シンボル

setMaxStruct(f); 

に専用のチェック構造体を定義するような何かを書きます

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

以下は、完全な作業例

#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; 
} 

で次のあなたは、あなたがsize_t(-1)g()が未定義である)を取得し、h()からあなたが63(最大値を取得しgから、4を取得fからそれを守ってマイナス1)。

関連する問題