2016-03-29 6 views
1

ラムダ/関数に使用するパラメータの量を問い合わせたいと思います。 小(擬似)コード例:私が求めています機能がnumber_of_arguments(...)であることラムダ/関数からの引数の数を問い合わせる

template <class InputIterator, class Predicate> 
bool visitAll(InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr) 
{ 
    for(; f != l; ++f) 
    { 
     if(number_of_arguments(p) == 1) 
     { 
      if(!p(*f)) 
       return false; 
     } 
     else 
     { 
      if(!p(*f, *d)) 
       return false; 
     } 
    } 
} 

注意。 私はClosureとstd :: functionのリファレンスを検索していましたが、解決策の手掛かりは見つかりませんでした。

ありがとうございました!

+1

標準ライブラリ関数(たとえば[標準ライブラリアルゴリズム関数](http://en.cppreference.com/w/cpp/algorithm))を使って標準ライブラリ関数を詳しく見てみると、そのような機能を持っていないことを確認してください。代わりに、異なる述語が必要な場合は、異なるオーバーロードがあります。 –

答えて

1

投稿したコードは明らかに意味がありません。とにかくp(*f)またはp(*f, *d)のいずれもコンパイルに失敗します。したがって、あなたは、2つのテンプレートにこれを分割し、その後、あなたはかなり単純SFINAEのアプローチを使用してPredicateの引数の数をテストすることができます必要があります。

template <class InputIterator, class Predicate> 
bool visitAll(InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr, 
    decltype(declval<Predicate>()(*declval<InputIterator>()),1) unused = 1) 
{ 
    cout << "1" << std::endl; 
    for(; f != l; ++f) 
    { 
     if(!p(*f)) 
      return false; 
    } 
    return true; 
} 

template <class InputIterator, class Predicate> 
bool visitAll(InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr, 
    decltype(declval<Predicate>()(*declval<InputIterator>(), declval<UserData>()),1) unused = 1) 
{ 
    cout << "2" << std::endl; 
    for(; f != l; ++f) 
    { 
     if(!p(*f, *d)) 
      return false; 
    } 
    return true; 
} 

使用法:もちろん

std::vector<int> a{1,2}; 
const auto t = [](int x){ return 1;}; 
const auto t2 = [](int x, UserData y){ return 1;}; 

UserData d; 
visitAll(a.begin(), a.end(), t); 
visitAll(a.begin(), a.end(), t2, &d); 

、あなたが使用することができますがstd::bindを使用して、2番目のバージョンから最初のバージョンを呼び出すことによってコードの重複を回避します。


別のアプローチには、引数の必要数得たことをどのようにstd::bindチェックに類似したコードを使用することです。おそらくいくつかのより多くのけれども

template<typename _Func> 
struct noa_helper { 
}; 

template<typename _Ret, typename... _Args> 
struct noa_helper<_Ret (*)(_Args...)> { 
    static int noa() { return sizeof...(_Args); } 
}; 

template<class F> 
int number_of_arguments(F f) { 
    return noa_helper<typename std::decay<F>::type>::noa(); 
} 

void foo(); 
int bar(int x, int y); 
... 
std::cout << number_of_arguments(foo) << std::endl; // prints 0 
std::cout << number_of_arguments(bar) << std::endl; // prints 2 

これは実関数ではなく、ラムダのためにのみ動作し、またstd::functionを、テンプレートマジックは、後者の2つのカテゴリでうまく機能させることができます。

+0

擬似コードはもちろん、インテントのみを視覚化する必要があります。良い答えをありがとう!コードがsegfaultに実行されても、それを実行させるためにわずかな変更だけが必要でした: UserData d; visitAll(a.begin()、a.end()、t2、&d); )そうしないと、nullptrが参照解除されてしまいます。 – nesono

関連する問題