2016-03-29 25 views
1

我想查詢一個lambda /函數關於它使用多少參數。 小(僞)示例代碼:從lambda /函數查詢參數的個數

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

注意,我要求的功能number_of_arguments(...)。 我一直在Closure和std :: function參考中搜索,但沒有找到解決方案的線索。

感謝您的幫助!

+1

這是不可能的,並且如果仔細觀察採用謂詞的標準庫函數(例如[標準庫算法函數](http://en.cppreference.com/w/cpp/algorithm)),您將看到他們都沒有這種功能,如果他們需要不同的謂詞,他們會有不同的重載。 –

回答

1

很明顯,您發佈的代碼沒有多大意義,因爲無論如何,p(*f)p(*f, *d)都無法編譯。因此,你需要把這個分成兩個模板,然後你可以使用一個相當簡單的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通過從第二個版本調用第一個版本來避免代碼重複。


另一種方法是使用相似的代碼如何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 

這僅適用於真正的功能,而不是lambda表達式,也不std::function,雖然可能更多一些模板魔法可以使它適用於後兩類。

+0

當然,僞代碼只能將意圖可視化。謝謝你的好回答!即使代碼運行到段錯誤,只需稍作更改即可運行: UserData d; visitAll(a.begin(),a.end(),t2,&d); 否則,nullptr將被解除引用。 – nesono