2013-07-04 3 views
1

Я пытаюсь изучить boost :: phoenix и пытаюсь использовать его в std :: transform, как показано ниже.boost :: сообщение об ошибке phoenix при использовании в качестве функтора

class myClass 
{ 
    int i; 

public: 
    getNumber(); 
    setNumber(int j); 
}; 

int main() 
{ 
    std::vector<myClass*> vect 
    std::vector<int> numVect 

    numVect.resize(vect.size()); 
    using boost::phoenix::arg_names::arg1; 
    std::transform (vect.begin(), vect.end(), numVect.begin(), arg1->getNumber()); 
} 

Но, я получаю сообщение об ошибке error: base operand of '->' has non-pointer type 'const boost::phoenix::actor<boost::phoenix::argument<0> >'

Я не совсем уверен, что это значит. Любая помощь будет большой. Благодаря

+0

Я предлагаю вам отказаться. Не принимайте это неправильно - я просто думаю, что Phoenix слишком сложна для использования на самом деле, и вы нашли отличный пример того, почему большинство пользователей C++ никогда не смогут помочь вам исправить это, как изменить его позже. Просто используйте обычный цикл или что-то в этом роде. –

+0

Я ценю ваше мнение. Но, я думаю, я просто нашел правильный способ сделать это std :: transform (vect.begin(), vect.end(), std :: back_insterter (numVect), (arg1 -> * & getNumber)()); – polapts

+2

Отлично. Теперь забудьте, что вы когда-либо знали об этом, и будущие сопровождающие вашего кода будут вам больше нравиться. :) В любом случае, не стесняйтесь публиковать свой собственный ответ, если вы получаете полностью работоспособную версию, закодированную с использованием тех же имен, что и в вашем вопросе. –

ответ

2

Как вы заметили выше, способ сделать это с помощью Феникса с phoenix::bind или ->*, как вы выше:

#include <vector> 
#include <boost/phoenix/core.hpp> 
#include <boost/phoenix/operator.hpp> 
#include <boost/range/algorithm/transform.hpp> 

class myClass 
{ 
    int i; 

public: 
    int getNumber() { return i; } 
    void setNumber(int j) { i = j; } 
}; 

int main() 
{ 
    std::vector<myClass*> vect; 
    std::vector<int> numVect; 

    using boost::phoenix::arg_names::arg1; 
    boost::transform(vect, 
        std::back_inserter(numVect), 
        (arg1->*&myClass::getNumber)()); 
} 

Phoenix может быть сложным, и связывать выражения являются одними из наиболее запутанным и ухитрился синтаксическими искажениями Феникса, но, честно говоря, этот не кажется таким уж плохим.

Полиморфные лямбды C++ 14, между прочим, избавят многих от Феникса.

+0

+1 Это приятный показ пуританского пути (в том числе 'back_inserter' :)). Тем не менее, я всегда предпочитаю 'bind' или' function <> 'какого-либо типа (я показываю использование' phoenix :: lambda' в моем ответе) – sehe

+0

PS. Реальный пуританский путь, конечно, был бы 'std :: mem_fn (& myClass :: getNumber)' ... но это не оправдало бы теги – sehe

0

Я хотел бы использовать

std::transform (vect.begin(), vect.end(), numVect.begin(), phx::bind(&myClass::getNumber, arg1)); 

Или, если вы хотите более хороший синтаксис:

auto getNumber = phx::lambda [ phx::bind(&myClass::getNumber, arg1) ]; 
std::transform (vect.begin(), vect.end(), numVect.begin(), getNumber(arg1)); 

Демо:

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

namespace phx = boost::phoenix; 

struct myClass 
{ 
    int i; 

    int getNumber() const { return i; } 
    void setNumber(int j) { i = j; } 
}; 

using namespace boost::phoenix::arg_names; 
static const auto getNumber = phx::lambda [ phx::bind(&myClass::getNumber, arg1) ]; 

int main() 
{ 
    const std::vector<myClass*> vect { new myClass{1}, new myClass{2}, new myClass{42} }; 
    std::vector<int> numVect(vect.size()); 

    // puritan/standard version: 
    std::transform (vect.begin(), vect.end(), numVect.begin(), std::mem_fn(&myClass::getNumber)); 

    // just bind: 
    std::transform (vect.begin(), vect.end(), numVect.begin(), phx::bind(&myClass::getNumber, arg1)); 

    // using more natural syntax 
    std::transform (vect.begin(), vect.end(), numVect.begin(), getNumber(arg1)); 

    for(auto i : numVect) 
     std::cout << i << " "; 
} 
Смежные вопросы