2013-08-28 3 views
2

Я не могу понять, как отправить именованную функцию в качестве аргумента другой функции, и включить аргумент в выражении лямбда phoenix.Как отправить именованную функцию в выражение boost :: phoenix

Вот минимальный пример, о котором я мог думать.

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <boost/phoenix.hpp> 

using namespace std; 
namespace ph = boost::phoenix; 
using ph::arg_names::arg1; 

template <typename Predicate> 
void foo(vector<int> &v, Predicate p) { 
    for_each(v.begin(), v.end(), 
     if_(p(arg1)) 
     [ 
     cout << "found " << arg1 << ", " 
     ]); 
    cout << endl; 
} 

bool is_odd(int i) { 
    return (i % 2 == 1); 
} 

main() { 
    vector<int> v(10); 
    int i = 1; 
    generate(v.begin(), v.end(), ph::ref(i)++); 
    cout << "looking for odd ones "; 
    foo(v, arg1 % 2 == 1); 

    cout << "using named function "; 
    //foo(v, is_odd); 
    //foo(v, &is_odd); 
    //foo(v, ph::bind(&is_odd, arg1)); 
    //foo(v, boost::bind(&is_odd, _1)); 
} 

Я не могу понять, как отправить функцию is_odd() в foo() как предикат.

Примечание: В моем фактическом коде предикат фактически является функцией членом arg1 (arg1 имеет class Bar, и мне нужно Bar::is_odd предиката). Я пробовал стиль (arg1->*&Bar::is_odd)(), но это не сработало. Я не включаю это в этот пример для простоты.

Обновление: Вот версия C++ 11 того же кода. Это один работает хорошо, однако, я хотел бы, чтобы заставить его работать с фениксом, так как я не могу использовать C++ 11

#include <vector> 
#include <iostream> 
#include <algorithm> 
using namespace std; 

template <typename Predicate> 
void foo(vector<int> &v, Predicate p) { 
    for_each(begin(v), end(v), 
     [&] (int i) { 
     if (p(i)) 
      cout << "found " << i << ", "; 
     }); 
    cout << endl; 
} 

bool is_odd(int i) { 
    return (i % 2 == 1); 
} 

main() { 
    vector<int> v={1,2,3,4,5,6,7,8,9,10}; 
    cout << "looking for odd ones "; 
    foo(v, [] (int i) {return (i%2 == 1);}); 

    cout << "using named function "; 
    foo(v, &is_odd); 
} 
+0

Вашей первый фрагмент кода также капает использование C++ 11 функций ... – sehe

+0

права, извини об этом. Исправлена. – yhager

+0

heh. хорошая работа - бит phoenix happy (или 'std :: iota' не в TR1?) – sehe

ответ

1

Там может быть другой, более простой, способ сделать это, но одна альтернатива использует функцию феникса (испытано на г ++ 4.8.1 без -std = C++ 11):

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <boost/phoenix.hpp> 

using namespace std; 
namespace ph = boost::phoenix; 
using ph::arg_names::arg1; 

bool is_odd(int i) { 
    return (i % 2 == 1); 
} 

struct is_odd_impl 
{ 
    template <typename Sig> 
    struct result; 

    template <typename This, typename Arg> 
    struct result<This(Arg)> 
    { 
    typedef bool type; 
    }; 

    template <typename Arg> 
    bool operator()(const Arg& arg) const 
    { 
    return is_odd(arg); 
    //return arg.is_odd(); 
    } 
}; 

ph::function<is_odd_impl> lazy_is_odd = is_odd_impl(); 

template <typename Predicate> 
void foo(vector<int> &v, Predicate p) { 
    for_each(v.begin(), v.end(), 
     if_(p(arg1)) 
     [ 
     cout << "found " << arg1 << ", " 
     ]); 
    cout << endl; 
} 



int main() { 
    vector<int> v(10); 
    int cont = 1; 
    std::generate(v.begin(),v.end(),ph::ref(cont)++); 

    cout << "looking for odd ones "; 
    foo(v, arg1 % 2 == 1); 

    cout << "using named function "; 
    foo(v, lazy_is_odd); 
} 
+0

Спасибо. Я не мог выполнить эту работу с макросами BOOST_PHOENIX_ADAPT, но ваш код работает. – yhager

Смежные вопросы